Merge "Replaced auto-fill by autofill to keep it consistent with API style."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b3db932..23dc206 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1506,19 +1506,13 @@
</activity>
<activity android:name="Settings$EnterprisePrivacySettingsActivity"
- android:label="@string/enterprise_privacy_settings_title"
- android:icon="@drawable/ic_settings_about"
- android:taskAffinity="com.android.settings"
- android:parentActivityName="Settings">
+ android:label="@string/enterprise_privacy_settings_title"
+ android:taskAffinity="com.android.settings"
+ android:parentActivityName="Settings$SecuritySettingsActivity">
<intent-filter>
<action android:name="android.settings.ENTERPRISE_PRIVACY_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- <intent-filter android:priority="-1">
- <action android:name="com.android.settings.action.SETTINGS" />
- </intent-filter>
- <meta-data android:name="com.android.settings.category"
- android:value="com.android.settings.category.ia.system" />
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.enterprise.EnterprisePrivacySettings" />
</activity>
@@ -2832,6 +2826,19 @@
android:value="com.android.settings.applications.ManageApplications" />
</activity>
+
+ <activity android:name="Settings$AppWriteSettingsActivity"
+ android:label="@string/write_settings_title"
+ android:taskAffinity="">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.action.MANAGE_WRITE_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="package" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.WriteSettingsDetails" />
+ </activity>
+
<activity android:name="Settings$ManageExternalSourcesActivity"
android:label="@string/install_other_apps"
android:taskAffinity="">
@@ -2843,16 +2850,16 @@
android:value="com.android.settings.applications.ManageApplications" />
</activity>
- <activity android:name="Settings$AppWriteSettingsActivity"
- android:label="@string/write_settings_title"
- android:taskAffinity="">
+ <activity android:name="Settings$ManageAppExternalSourcesActivity"
+ android:label="@string/install_other_apps"
+ android:taskAffinity="">
<intent-filter android:priority="1">
- <action android:name="android.settings.action.MANAGE_WRITE_SETTINGS" />
+ <action android:name="android.settings.action.MANAGE_EXTERNAL_SOURCES" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.applications.WriteSettingsDetails" />
+ android:value="com.android.settings.applications.ExternalSourcesDetails" />
</activity>
<activity android:name="ShowAdminSupportDetailsDialog"
diff --git a/res/layout/app_preferred_settings.xml b/res/layout/app_preferred_settings.xml
index d0041a1..1f3b497 100644
--- a/res/layout/app_preferred_settings.xml
+++ b/res/layout/app_preferred_settings.xml
@@ -14,36 +14,27 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<ScrollView
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:clipToPadding="false"
- android:scrollbarStyle="@integer/preference_scrollbar_style">
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingBottom="5dip"
+ android:orientation="vertical">
- <LinearLayout
- android:layout_width="match_parent"
+ <TextView android:id="@+id/auto_launch"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_alignParentStart="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="6dip" />
+
+ <Button
+ android:id="@+id/clear_activities_button"
+ android:layout_marginStart="-4dip"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:paddingBottom="5dip"
- android:orientation="vertical">
+ android:text="@string/clear_activities" />
- <TextView android:id="@+id/auto_launch"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_alignParentStart="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="6dip" />
-
- <Button
- android:id="@+id/clear_activities_button"
- android:layout_marginStart="-4dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/clear_activities" />
-
- </LinearLayout>
-
-</ScrollView>
+</LinearLayout>
diff --git a/res/layout/date_time_custom_list_item_2.xml b/res/layout/date_time_custom_list_item_2.xml
index ed32fb7..4902758 100644
--- a/res/layout/date_time_custom_list_item_2.xml
+++ b/res/layout/date_time_custom_list_item_2.xml
@@ -15,29 +15,28 @@
-->
<!-- Based on simple_list_item_2.xml in framework -->
-<TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:mode="twoLine"
+ android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
->
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical"
+ android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
- <TextView android:id="@android:id/text1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="16dip"
- android:layout_marginStart="10dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- />
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceListItem" />
- <TextView android:id="@android:id/text2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="10dip"
- android:layout_below="@android:id/text1"
- android:layout_alignStart="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary" />
-</TwoLineListItem>
+</LinearLayout>
diff --git a/res/layout/expand_preference.xml b/res/layout/expand_preference.xml
index 1392d65..d5fe031 100644
--- a/res/layout/expand_preference.xml
+++ b/res/layout/expand_preference.xml
@@ -56,9 +56,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
- android:textColor="?android:attr/colorAccent"
android:ellipsize="marquee"/>
<TextView
diff --git a/res/layout/preference_footer.xml b/res/layout/preference_footer.xml
index e336ac1..1df4f70 100644
--- a/res/layout/preference_footer.xml
+++ b/res/layout/preference_footer.xml
@@ -20,7 +20,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground"
@@ -31,15 +30,15 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="60dp"
- android:gravity="start|center_vertical"
+ android:gravity="start|top"
android:orientation="horizontal"
android:paddingEnd="12dp"
- android:paddingTop="4dp"
+ android:paddingTop="20dp"
android:paddingBottom="4dp">
- <com.android.internal.widget.PreferenceImageView
+ <ImageView
android:id="@android:id/icon"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content" />
</LinearLayout>
<com.android.settingslib.widget.LinkTextView
@@ -50,6 +49,6 @@
android:paddingTop="16dp"
android:maxLines="10"
android:textColor="?android:attr/textColorSecondary"
- android:ellipsize="marquee"/>
+ android:ellipsize="marquee" />
</LinearLayout>
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index d099cdc..d4f9d90 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -92,6 +92,8 @@
<attr name="apnPreferenceStyle" format="reference" />
+ <attr name="footerPreferenceStyle" format="reference" />
+
<!-- For Search -->
<declare-styleable name="Preference">
<attr name="keywords" format="string" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c9a1bf7..e7a0535 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4299,6 +4299,11 @@
<!-- Display time remaining until battery is charged [CHAR_LIMIT=60] -->
<string name="power_charge_remaining"><xliff:g id="until_charged">%1$s</xliff:g> to charge</string>
+ <!-- Title for the background activity setting, which allows a user to control whether an app can run in the background [CHAR_LIMIT=40] -->
+ <string name="background_activity_title">Background activity</string>
+ <!-- Summary for the background activity [CHAR_LIMIT=120] -->
+ <string name="background_activity_summary">Allow the app to run in the background</string>
+
<!-- Title for the screen usage in power use UI [CHAR_LIMIT=40] -->
<string name="device_screen_usage">Screen usage</string>
<!-- Title for the screen consumption in power use UI(i.e. Screen consumption: 30% of battery usage) [CHAR_LIMIT=40] -->
@@ -8114,64 +8119,58 @@
<!-- Enterprise Privacy --> <skip />
- <!-- Title of setting on main settings screen. This will take the user to a screen with information about his/her privacy on a managed device. Shown on enterprise-managed devices only. -->
- <string name="enterprise_privacy_settings">Privacy</string>
+ <!-- Title of setting on security settings screen. This will take the user to a screen with information about admin powers and their impact on the user's privacy on a managed device. Shown on enterprise-managed devices only. -->
+ <string name="enterprise_privacy_settings">Device management</string>
+ <!-- Summary for Enterprise Privacy settings, explaining what the user can expect to find under it [CHAR LIMIT=NONE]-->
+ <string name="enterprise_privacy_settings_summary">View all settings applied by your admin</string>
<!-- Enterprise Privacy settings activity title -->
- <string name="enterprise_privacy_settings_title">Privacy</string>
- <!-- Enterprise Privacy settings activity header, summarizing the powers that the admin has. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_header">To provide access to your work data, your organization may change settings and install software on your device, which could cause some of your personal content to be visible to your admin. Contact your organization\'s admin for more details.</string>
- <!-- Title for the 'What types of information can your organization see?' preference category. [CHAR LIMIT=60] -->
- <string name="enterprise_privacy_exposure_category">What types of information can your organization see?</string>
- <!-- Title for the 'What changes affect what your organization can see?' preference category. [CHAR LIMIT=60] -->
- <string name="enterprise_privacy_exposure_changes_category">What changes affect what your organization can see?</string>
- <!-- Title for the 'What actions may impact your access to this device?' preference category. [CHAR LIMIT=60] -->
- <string name="enterprise_privacy_device_access_category">What actions may impact your access to this device?</string>
+ <string name="enterprise_privacy_settings_title">Device management</string>
+ <!-- Enterprise Privacy settings activity footer, summarizing the powers that the admin has. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_footer">To provide access to your work data, your organization may change settings and install software on your device. \n\nFor more details, contact your organization\'s admin.</string>
+ <!-- Title for the 'Types of information your organization can see' preference category. [CHAR LIMIT=60] -->
+ <string name="enterprise_privacy_exposure_category">Types of information your organization can see</string>
+ <!-- Title for the 'Changes made by your organization’s admin' preference category. [CHAR LIMIT=60] -->
+ <string name="enterprise_privacy_exposure_changes_category">Changes made by your organization\'s admin</string>
+ <!-- Title for the 'Your access to this device' preference category. [CHAR LIMIT=60] -->
+ <string name="enterprise_privacy_device_access_category">Your access to this device</string>
<!-- Label explaining that the admin can see data associated with his/her work account. [CHAR LIMIT=NONE] -->
<string name="enterprise_privacy_enterprise_data">Data associated with your work account, such as email and calendar</string>
- <!-- Label explaining that the admin can see all apps installed on the device. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_number_installed_packages_default">List of all apps on your device</string>
- <!-- Label explaining that the admin can see all apps installed on the device. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_installed_packages">
- <item quantity="one">List of all <xliff:g id="count">%d</xliff:g> app on your device</item>
- <item quantity="other">List of all <xliff:g id="count">%d</xliff:g> apps on your device</item>
+ <!-- Label explaining that the admin can see apps installed on the device. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_installed_packages">List of apps on your device</string>
+ <!-- Summary indicating the number of apps that a label (e.g. installed apps or apps granted a particular permission) refers to. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_number_packages">
+ <item quantity="one"><xliff:g id="count">%d</xliff:g> app</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> apps</item>
+ </plurals>
+ <!-- Summary indicating the number of apps that a label (e.g. installed apps or apps granted a particular permission) refers to. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_number_packages_actionable">
+ <item quantity="one"><xliff:g id="count">%d</xliff:g> app. Tap to view.</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> apps. Tap to view.</item>
</plurals>
<!-- Label explaining that the admin can see app usage statistics. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_usage_stats">Usage (time spent and amount of data used) of each app on your device</string>
+ <string name="enterprise_privacy_usage_stats">Time and data spent in each app on your device</string>
<!-- Label explaining that the admin can retrieve network logs on the device. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_network_logs">Traffic logs on your device</string>
+ <string name="enterprise_privacy_network_logs">Network traffic logs on your device</string>
<!-- Label explaining that the admin can request bug reports on the device. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_bug_reports">Your most recent bug report</string>
+ <string name="enterprise_privacy_bug_reports">Most recent bug report</string>
<!-- Label explaining that the admin can retrieve security on from the device. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_security_logs">Your most recent security log</string>
- <!-- Label indicating that the date at which the admin last took a particular action was "never" (i.e. the admin never took the action so far). -->
- <string name="enterprise_privacy_never">Never</string>
- <!-- Label indicating how many apps were installed on the device by the admin. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_enterprise_installed_packages">
- <item quantity="one"><xliff:g id="count">%d</xliff:g> app installed by your admin</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> apps installed by your admin</item>
- </plurals>
- <!-- Label indicating how many apps were granted permission to access the device's location by the admin. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_location_access_packages">
- <item quantity="one"><xliff:g id="count">%d</xliff:g> app allowed access to your location by your admin</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> apps allowed access to your location by your admin</item>
- </plurals>
- <!-- Label indicating how many apps were granted permission to access the microphone by the admin. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_microphone_access_packages">
- <item quantity="one"><xliff:g id="count">%d</xliff:g> app allowed access to your microphone by your admin</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> apps allowed access to your microphone by your admin</item>
- </plurals>
- <!-- Label indicating how many apps were granted permission to access the camera by the admin. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_camera_access_packages">
- <item quantity="one"><xliff:g id="count">%d</xliff:g> app allowed access to your camera by your admin</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> apps allowed access to your camera by your admin</item>
- </plurals>
- <!-- Label indicating how many apps were set as default defaults for common actions (e.g. open browser, send e-mail) by the admin. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_number_enterprise_set_default_apps">
- <item quantity="one"><xliff:g id="count">%d</xliff:g> default app set by your admin</item>
- <item quantity="other"><xliff:g id="count">%d</xliff:g> default apps set by your admin</item>
- </plurals>
+ <string name="enterprise_privacy_security_logs">Most recent security log</string>
+ <!-- Label indicating that the the admin never took a given action so far (e.g. did not retrieve security logs or request bug reports). -->
+ <string name="enterprise_privacy_none">None</string>
+ <!-- Label indicating that the admin installed one or more apps on the device. -->
+ <string name="enterprise_privacy_enterprise_installed_packages">Apps installed</string>
+ <!-- Label indicating that the admin granted one or more apps access to the device's location. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_location_access">Apps allowed to access your location</string>
+ <!-- Label indicating that the admin granted one or more apps access to the microphone. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_microphone_access">Apps allowed to access your microphone</string>
+ <!-- Label indicating that the admin granted one or more apps access to the camera. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_camera_access">Apps allowed to access your camera</string>
+ <!-- Label indicating that the admin set one or more apps as defaults for common actions (e.g. open browser, send e-mail). [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_enterprise_set_default_apps">Default apps set</string>
<!-- Label explaining that the current input method was set by the admin. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_input_method">Default keyboard set to <xliff:g id="app_label" example="Example Keyboard">%s</xliff:g> by your admin</string>
+ <string name="enterprise_privacy_input_method">Default keyboard</string>
+ <!-- Summary indicating the input method set by the admin. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_input_method_name">Set to <xliff:g id="app_label" example="Example Keyboard">%s</xliff:g></string>
<!-- Label explaining that an always-on VPN was set by the admin for the entire device. [CHAR LIMIT=NONE] -->
<string name="enterprise_privacy_always_on_vpn_device">Always-on VPN turned on</string>
<!-- Label explaining that an always-on VPN was set by the admin in the personal profile. [CHAR LIMIT=NONE] -->
@@ -8180,22 +8179,46 @@
<string name="enterprise_privacy_always_on_vpn_work">Always-on VPN turned on in your work profile</string>
<!-- Label explaining that a global HTTP proxy was set by the admin. [CHAR LIMIT=NONE] -->
<string name="enterprise_privacy_global_http_proxy">Global HTTP proxy set</string>
+ <!-- Label explaining that the admin installed trusted CA certificates for the current user. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_ca_certs_user">
+ <item quantity="one">Trusted CA Certificate installed</item>
+ <item quantity="other">Trusted CA Certificates installed</item>
+ </plurals>
+ <!-- Label explaining that the admin installed trusted CA certificates for the personal profile. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_ca_certs_personal">
+ <item quantity="one">Trusted CA Certificate installed in the personal profile</item>
+ <item quantity="other">Trusted CA Certificates installed in the personal profile</item>
+ </plurals>
+ <!-- Summary indicating the number of trusted CA certificates installed by the admin. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_number_ca_certs">
+ <item quantity="one"><xliff:g id="count">%d</xliff:g> certificate</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> certificates</item>
+ </plurals>
+ <!-- Summary indicating the number of trusted CA certificates installed by the admin. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_number_ca_certs_actionable">
+ <item quantity="one"><xliff:g id="count">%d</xliff:g> certificate. Tap to view.</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> certificates. Tap to view.</item>
+ </plurals>
+ <!-- Label explaining that the admin installed trusted CA certificates for the work profile. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_ca_certs_work">
+ <item quantity="one">Trusted CA Certificate installed in the work profile</item>
+ <item quantity="other">Trusted CA Certificates installed in the work profile</item>
+ </plurals>
<!-- Label explaining that the admin can lock the device and change the user's password. [CHAR LIMIT=NONE] -->
- <string name="enterprise_privacy_lock_device">Admin can lock device and reset password</string>
+ <string name="enterprise_privacy_lock_device">Admin can lock the device and reset password</string>
<!-- Label explaining that the admin can wipe the device remotely. [CHAR LIMIT=NONE] -->
<string name="enterprise_privacy_wipe_device">Admin can delete all device data</string>
- <!-- Label explaining that the admin configured the device to wipe itself when the password is mistyped this many times. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_failed_password_wipe_device">
- <item quantity="one">Admin set maximum password attempts to <xliff:g id="count">%d</xliff:g> before deleting all device data</item>
- <item quantity="other">Admin set maximum password attempts to <xliff:g id="count">%d</xliff:g> before deleting all device data</item>
- </plurals>
- <!-- Label explaining that the admin configured the work profile to wipe itself when the password is mistyped this many times. [CHAR LIMIT=NONE] -->
- <plurals name="enterprise_privacy_failed_password_wipe_work">
- <item quantity="one">Admin set maximum password attempts to <xliff:g id="count">%d</xliff:g> before deleting work profile data</item>
- <item quantity="other">Admin set maximum password attempts to <xliff:g id="count">%d</xliff:g> before deleting work profile data</item>
+ <!-- Label explaining that the admin configured the device to wipe itself when the password is mistyped too many times. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_failed_password_wipe_device">Failed password attempts before deleting all device data</string>
+ <!-- Label explaining that the admin configured the work profile to wipe itself when the password is mistyped too many times. [CHAR LIMIT=NONE] -->
+ <string name="enterprise_privacy_failed_password_wipe_work">Failed password attempts before deleting work profile data</string>
+ <!-- Summary indicating the number of mistyped passwords after which the device or work profile wipes itself. [CHAR LIMIT=NONE] -->
+ <plurals name="enterprise_privacy_number_failed_password_wipe">
+ <item quantity="one"><xliff:g id="count">%d</xliff:g> attempt</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> attempts</item>
</plurals>
<!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
- <string name="do_disclosure_generic">This device is managed.</string>
+ <string name="do_disclosure_generic">This device is managed by your organization.</string>
<!-- Message indicating that the device is enterprise-managed by a Device Owner [CHAR LIMIT=NONE] -->
<string name="do_disclosure_with_name">This device is managed by <xliff:g id="organization_name" example="Foo, Inc.">%s</xliff:g>.</string>
<!-- Message indicating that the device is enterprise-managed: Space that separates the main text and the "learn more" link that follows it. [CHAR LIMIT=NONE] -->
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index e7c2852..8271df4 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -38,6 +38,11 @@
<item name="android:layout">@layout/apn_preference_layout</item>
</style>
+ <style name="FooterPreference" parent="SettingsPreference">
+ <item name="android:layout">@layout/preference_footer</item>
+ <item name="allowDividerAbove">true</item>
+ </style>
+
<style name="EditTextPreference"
parent="@style/Preference.DialogPreference.EditTextPreference.Material">
<item name="allowDividerAbove">false</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index d6df2ab..99e2133 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -81,6 +81,7 @@
<!-- Parent path frameworks/support/v14/preference/res/values/themes.xml -->
<item name="android:scrollbars">vertical</item>
<item name="apnPreferenceStyle">@style/ApnPreference</item>
+ <item name="footerPreferenceStyle">@style/FooterPreference</item>
<item name="dialogPreferenceStyle">@style/SettingsDialogPreference</item>
<item name="dropdownPreferenceStyle">@style/SettingsDropdownPreference</item>
<item name="editTextPreferenceStyle">@style/EditTextPreference</item>
@@ -102,8 +103,10 @@
<!-- Accessibility portion of Setup Wizard -->
<style name="SetupWizardAccessibilityTheme" parent="Theme.SettingsBase">
+ <item name="android:windowLightStatusBar">false</item>
<item name="android:colorPrimary">@color/material_blue_700</item>
<item name="android:colorPrimaryDark">@color/material_blue_700</item>
+ <item name="android:actionBarTheme">@android:style/ThemeOverlay.Material.Dark.ActionBar</item>
<item name="preferenceTheme">@style/PreferenceTheme</item>
<item name="switchBarTheme">@style/SetupWizardAccessibilitySwitchBarTheme</item>
</style>
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index 34d48f1..7859119 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -44,7 +44,7 @@
/>
<Preference
- android:fragment="com.android.settings.ZonePicker"
+ android:fragment="com.android.settings.datetime.ZonePicker"
android:key="timezone"
android:title="@string/date_time_set_timezone"
android:summary="GMT-8:00"
diff --git a/res/xml/device_info_status.xml b/res/xml/device_info_status.xml
index 1b173f1..9a57af9 100644
--- a/res/xml/device_info_status.xml
+++ b/res/xml/device_info_status.xml
@@ -14,64 +14,76 @@
limitations under the License.
-->
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/device_status_activity_title">
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/device_status_activity_title">
- <com.android.settings.CopyablePreference android:key="battery_status"
+ <Preference
+ android:key="battery_status"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/battery_status_title"
- android:summary="@string/device_info_not_available"
- android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="battery_level"
+ android:summary="@string/device_info_not_available" />
+ <Preference
+ android:key="battery_level"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/battery_level_title"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <Preference android:key="sim_status"
+ <Preference
+ android:key="sim_status"
android:title="@string/sim_status_title"
android:persistent="false">
- <intent android:targetPackage="com.android.settings"
+ <intent
+ android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Settings$SimStatusActivity" />
</Preference>
- <Preference android:key="imei_info"
+ <Preference
+ android:key="imei_info"
android:title="@string/imei_information_title"
android:persistent="false">
- <intent android:targetPackage="com.android.settings"
+ <intent
+ android:targetPackage="com.android.settings"
android:targetClass="com.android.settings.Settings$ImeiInformationActivity" />
</Preference>
- <com.android.settings.CopyablePreference android:key="wifi_ip_address"
+ <Preference
+ android:key="wifi_ip_address"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/wifi_advanced_ip_address_title"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="wifi_mac_address"
+ <Preference
+ android:key="wifi_mac_address"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/status_wifi_mac_address"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="bt_address"
+ <Preference
+ android:key="bt_address"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/status_bt_address"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="serial_number"
+ <Preference
+ android:key="serial_number"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/status_serial_number"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="up_time"
+ <Preference
+ android:key="up_time"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/status_up_time"
android:summary="@string/device_info_not_available"
android:persistent="false" />
- <com.android.settings.CopyablePreference android:key="wimax_mac_address"
+ <Preference
+ android:key="wimax_mac_address"
android:enabled="false"
android:shouldDisableView="false"
android:title="@string/status_wimax_mac_address"
diff --git a/res/xml/enterprise_privacy_settings.xml b/res/xml/enterprise_privacy_settings.xml
index 992c753..f08b9f2 100644
--- a/res/xml/enterprise_privacy_settings.xml
+++ b/res/xml/enterprise_privacy_settings.xml
@@ -19,83 +19,75 @@
android:key="enterprise_privacy_settings"
android:title="@string/enterprise_privacy_settings_title">
- <!-- Header -->
- <Preference android:key="enterprise_privacy_header"
- android:summary="@string/enterprise_privacy_header"
- android:selectable="false"/>
-
<PreferenceCategory android:title="@string/enterprise_privacy_exposure_category">
<com.android.settings.DividerPreference
android:key="enterprise_data"
android:layout_height="wrap_content"
android:title="@string/enterprise_privacy_enterprise_data"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
- android:key="number_installed_packages"
- android:title="@string/enterprise_privacy_number_installed_packages_default"
- settings:allowDividerBelow="true"
+ android:key="installed_packages"
+ android:title="@string/enterprise_privacy_installed_packages"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="usage_stats"
android:title="@string/enterprise_privacy_usage_stats"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="network_logs"
android:title="@string/enterprise_privacy_network_logs"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="bug_reports"
android:title="@string/enterprise_privacy_bug_reports"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="security_logs"
android:title="@string/enterprise_privacy_security_logs"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/enterprise_privacy_exposure_changes_category">
<com.android.settings.DividerPreference
android:key="number_enterprise_installed_packages"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_enterprise_installed_packages"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="enterprise_privacy_number_location_access_packages"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_location_access"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="enterprise_privacy_number_microphone_access_packages"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_microphone_access"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="enterprise_privacy_number_camera_access_packages"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_camera_access"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="number_enterprise_set_default_apps"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_enterprise_set_default_apps"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="always_on_vpn_primary_user"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="always_on_vpn_managed_profile"
android:title="@string/enterprise_privacy_always_on_vpn_work"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="input_method"
- settings:allowDividerBelow="true"
+ android:title="@string/enterprise_privacy_input_method"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="global_http_proxy"
android:title="@string/enterprise_privacy_global_http_proxy"
- settings:allowDividerBelow="true"
+ settings:multiLine="true"/>
+ <com.android.settings.DividerPreference
+ android:key="ca_certs_current_user"
+ settings:multiLine="true"/>
+ <com.android.settings.DividerPreference
+ android:key="ca_certs_managed_profile"
settings:multiLine="true"/>
</PreferenceCategory>
@@ -103,20 +95,20 @@
<com.android.settings.DividerPreference
android:key="lock_device"
android:title="@string/enterprise_privacy_lock_device"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="wipe_device"
android:title="@string/enterprise_privacy_wipe_device"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="failed_password_wipe_primary_user"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
<com.android.settings.DividerPreference
android:key="failed_password_wipe_managed_profile"
- settings:allowDividerBelow="true"
settings:multiLine="true"/>
</PreferenceCategory>
+
+ <com.android.settings.widget.FooterPreference
+ android:title="@string/enterprise_privacy_footer"
+ android:selectable="false"/>
</PreferenceScreen>
diff --git a/res/xml/installed_app_launch_settings.xml b/res/xml/installed_app_launch_settings.xml
index 7342cc0..ac77be1 100644
--- a/res/xml/installed_app_launch_settings.xml
+++ b/res/xml/installed_app_launch_settings.xml
@@ -37,8 +37,7 @@
android:title="@string/app_launch_other_defaults_title">
<com.android.settings.applications.ClearDefaultsPreference
- android:key="app_launch_clear_defaults"
- />
+ android:key="app_launch_clear_defaults" />
</PreferenceCategory>
diff --git a/res/xml/power_usage_details.xml b/res/xml/power_usage_details.xml
index 724aae8..86aa4f5 100644
--- a/res/xml/power_usage_details.xml
+++ b/res/xml/power_usage_details.xml
@@ -26,6 +26,11 @@
android:key="controls_parent"
android:title="@string/controls_subtitle">
+ <SwitchPreference
+ android:key="background_activity"
+ android:title="@string/background_activity_title"
+ android:summary="@string/background_activity_summary"/>
+
<Preference
android:key="high_power"
android:title="@string/high_power_apps" />
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 04272df..155f21a 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -43,6 +43,12 @@
android:persistent="false"
android:fragment="com.android.settings.DeviceAdminSettings"/>
+ <Preference android:key="enterprise_privacy"
+ android:title="@string/enterprise_privacy_settings"
+ android:summary="@string/enterprise_privacy_settings_summary"
+ android:persistent="false"
+ android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"/>
+
</PreferenceCategory>
<Preference android:key="sim_lock_settings"
diff --git a/res/xml/user_and_accounts_settings.xml b/res/xml/user_and_accounts_settings.xml
index bc3ac6c..6280980 100644
--- a/res/xml/user_and_accounts_settings.xml
+++ b/res/xml/user_and_accounts_settings.xml
@@ -23,7 +23,8 @@
<Preference
android:key="emergency_info"
android:title="@string/emergency_info_title"
- android:order="100"/>
+ android:order="100"
+ settings:allowDividerAbove="true"/>
<PreferenceCategory
android:key="account_configuration_header"
diff --git a/src/com/android/settings/CopyablePreference.java b/src/com/android/settings/CopyablePreference.java
deleted file mode 100644
index 03147c2..0000000
--- a/src/com/android/settings/CopyablePreference.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-package com.android.settings;
-
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.View.OnLongClickListener;
-import android.widget.Toast;
-
-public class CopyablePreference extends Preference {
-
- public CopyablePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public CopyablePreference(Context context) {
- this(context, null);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder holder) {
- super.onBindViewHolder(holder);
- holder.setDividerAllowedAbove(true);
- holder.setDividerAllowedBelow(true);
- holder.itemView.setLongClickable(true);
- holder.itemView.setOnLongClickListener(new OnLongClickListener() {
- @Override
- public boolean onLongClick(View v) {
- copyPreference(getContext(), CopyablePreference.this);
- return true;
- }
- });
- }
-
- public CharSequence getCopyableText() {
- return getSummary();
- }
-
- public static void copyPreference(Context context, CopyablePreference pref) {
- ClipboardManager cm =
- (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- 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/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 1bd7416..fb590cc 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -521,6 +521,14 @@
return result;
}
+ private static CharSequence getActiveTrustAgentLabel(Context context,
+ TrustAgentManager trustAgentManager, LockPatternUtils utils,
+ DevicePolicyManager dpm) {
+ ArrayList<TrustAgentComponentInfo> agents = getActiveTrustAgents(context,
+ trustAgentManager, utils, dpm);
+ return agents.isEmpty() ? null : agents.get(0).title;
+ }
+
@Override
public void onGearClick(GearPreference p) {
if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
@@ -908,6 +916,7 @@
private SwitchPreference mPowerButtonInstantlyLocks;
private RestrictedPreference mOwnerInfoPref;
+ private TrustAgentManager mTrustAgentManager;
private LockPatternUtils mLockPatternUtils;
private DevicePolicyManager mDPM;
@@ -919,6 +928,9 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ SecurityFeatureProvider securityFeatureProvider =
+ FeatureFactory.getFactory(getActivity()).getSecurityFeatureProvider();
+ mTrustAgentManager = securityFeatureProvider.getTrustAgentManager();
mLockPatternUtils = new LockPatternUtils(getContext());
mDPM = getContext().getSystemService(DevicePolicyManager.class);
createPreferenceHierarchy();
@@ -973,13 +985,12 @@
// lock instantly on power key press
mPowerButtonInstantlyLocks = (SwitchPreference) findPreference(
KEY_POWER_INSTANTLY_LOCKS);
- Preference trustAgentPreference = findPreference(KEY_TRUST_AGENT);
- if (mPowerButtonInstantlyLocks != null &&
- trustAgentPreference != null &&
- trustAgentPreference.getTitle().length() > 0) {
+ CharSequence trustAgentLabel = getActiveTrustAgentLabel(getContext(),
+ mTrustAgentManager, mLockPatternUtils, mDPM);
+ if (mPowerButtonInstantlyLocks != null && !TextUtils.isEmpty(trustAgentLabel)) {
mPowerButtonInstantlyLocks.setSummary(getString(
R.string.lockpattern_settings_power_button_instantly_locks_summary,
- trustAgentPreference.getTitle()));
+ trustAgentLabel));
}
mOwnerInfoPref = (RestrictedPreference) findPreference(KEY_OWNER_INFO_SETTINGS);
@@ -1048,14 +1059,15 @@
}
}
- Preference preference = findPreference(KEY_TRUST_AGENT);
- if (preference != null && preference.getTitle().length() > 0) {
+ CharSequence trustAgentLabel = getActiveTrustAgentLabel(getContext(),
+ mTrustAgentManager, mLockPatternUtils, mDPM);
+ if (!TextUtils.isEmpty(trustAgentLabel)) {
if (Long.valueOf(values[best].toString()) == 0) {
summary = getString(R.string.lock_immediately_summary_with_exception,
- preference.getTitle());
+ trustAgentLabel);
} else {
summary = getString(R.string.lock_after_timeout_summary_with_exception,
- entries[best], preference.getTitle());
+ entries[best], trustAgentLabel);
}
} else {
summary = getString(R.string.lock_after_timeout_summary, entries[best]);
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 2b486aa..f2d6452 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -131,6 +131,7 @@
public static class ManageExternalSourcesActivity extends SettingsActivity {
/* empty */ }
+ public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
public static class WifiCallingSuggestionActivity extends SettingsActivity { /* empty */ }
public static class ZenModeAutomationSuggestionActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index ffc051e..7d6cf77 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -32,7 +32,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.nfc.NfcAdapter;
@@ -661,6 +660,9 @@
@Override
protected void onPause() {
super.onPause();
+ mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
+ mDevelopmentPreferencesListener);
+ mDevelopmentPreferencesListener = null;
unregisterReceiver(mBatteryInfoReceiver);
if (!mSearchFeatureProvider.isEnabled(this)) {
unregisterReceiver(mUserAddRemoveReceiver);
@@ -671,15 +673,6 @@
}
@Override
- public void onDestroy() {
- super.onDestroy();
-
- mDevelopmentPreferences.unregisterOnSharedPreferenceChangeListener(
- mDevelopmentPreferencesListener);
- mDevelopmentPreferencesListener = null;
- }
-
- @Override
public void setTaskDescription(ActivityManager.TaskDescription taskDescription) {
final Bitmap icon = getBitmapFromXmlResource(R.drawable.ic_launcher_settings);
taskDescription.setIcon(icon);
@@ -895,32 +888,32 @@
pm.hasSystemFeature(PackageManager.FEATURE_WIFI), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.BluetoothSettingsActivity.class.getName()),
+ Settings.BluetoothSettingsActivity.class.getName()),
pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.DataUsageSummaryActivity.class.getName()),
+ Settings.DataUsageSummaryActivity.class.getName()),
Utils.isBandwidthControlEnabled(), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.SimSettingsActivity.class.getName()),
+ Settings.SimSettingsActivity.class.getName()),
Utils.showSimCardTile(this), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.PowerUsageSummaryActivity.class.getName()),
+ Settings.PowerUsageSummaryActivity.class.getName()),
mBatteryPresent, isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.UserSettingsActivity.class.getName()),
+ Settings.UserSettingsActivity.class.getName()),
UserHandle.MU_ENABLED && UserManager.supportsMultipleUsers()
- && !Utils.isMonkeyRunning(), isAdmin);
+ && !Utils.isMonkeyRunning(), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.NetworkDashboardActivity.class.getName()),
+ Settings.NetworkDashboardActivity.class.getName()),
!UserManager.isDeviceInDemoMode(this), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.ConnectedDeviceDashboardActivity.class.getName()),
+ Settings.ConnectedDeviceDashboardActivity.class.getName()),
!UserManager.isDeviceInDemoMode(this), isAdmin);
setTileEnabled(new ComponentName(packageName,
@@ -934,42 +927,46 @@
&& adapter != null && adapter.isEnabled(), isAdmin);
setTileEnabled(new ComponentName(packageName,
- Settings.PrintSettingsActivity.class.getName()),
+ Settings.PrintSettingsActivity.class.getName()),
pm.hasSystemFeature(PackageManager.FEATURE_PRINTING), isAdmin);
final boolean showDev = mDevelopmentPreferences.getBoolean(
- DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng"))
+ DevelopmentSettings.PREF_SHOW, android.os.Build.TYPE.equals("eng"))
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
setTileEnabled(new ComponentName(packageName,
Settings.DevelopmentSettingsActivity.class.getName()),
showDev, isAdmin);
+ // Enable/disable backup settings depending on whether the user is admin.
+ setTileEnabled(new ComponentName(packageName,
+ BackupSettingsActivity.class.getName()), true,
+ isAdmin || Utils.isCarrierDemoUser(this));
+
+ setTileEnabled(new ComponentName(packageName,
+ Settings.EnterprisePrivacySettingsActivity.class.getName()),
+ FeatureFactory.getFactory(this).getEnterprisePrivacyFeatureProvider(this)
+ .hasDeviceOwner(), isAdmin);
+
if (UserHandle.MU_ENABLED && !isAdmin) {
+
// When on restricted users, disable all extra categories (but only the settings ones).
final List<DashboardCategory> categories = mDashboardFeatureProvider.getAllCategories();
-
- for (DashboardCategory category : categories) {
- for (Tile tile : category.tiles) {
- ComponentName component = tile.intent.getComponent();
- final String name = component.getClassName();
- final boolean isEnabledForRestricted = ArrayUtils.contains(
- SettingsGateway.SETTINGS_FOR_RESTRICTED, name);
- if (packageName.equals(component.getPackageName()) && !isEnabledForRestricted) {
- setTileEnabled(component, false, isAdmin);
+ synchronized (categories) {
+ for (DashboardCategory category : categories) {
+ for (Tile tile : category.tiles) {
+ ComponentName component = tile.intent.getComponent();
+ final String name = component.getClassName();
+ final boolean isEnabledForRestricted = ArrayUtils.contains(
+ SettingsGateway.SETTINGS_FOR_RESTRICTED, name);
+ if (packageName.equals(component.getPackageName())
+ && !isEnabledForRestricted) {
+ setTileEnabled(component, false, isAdmin);
+ }
}
}
}
}
- // Enable/disable backup settings depending on whether the user is admin.
- setTileEnabled(new ComponentName(packageName,
- BackupSettingsActivity.class.getName()), true,
- isAdmin || Utils.isCarrierDemoUser(this));
-
- setTileEnabled(new ComponentName(packageName,
- Settings.EnterprisePrivacySettingsActivity.class.getName()),
- FeatureFactory.getFactory(this).getEnterprisePrivacyFeatureProvider(this)
- .hasDeviceOwner(), isAdmin);
// Final step, refresh categories.
updateCategories();
}
@@ -1099,10 +1096,6 @@
return mResultIntentData;
}
- public void setResultIntentData(Intent resultIntentData) {
- mResultIntentData = resultIntentData;
- }
-
public void startSuggestion(Intent intent) {
if (intent == null || ActivityManager.isUserAMonkey()) {
return;
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 350ab9c..f267640 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -302,13 +302,6 @@
return formatPercentage(getBatteryLevel(batteryChangedIntent));
}
- public static void forcePrepareCustomPreferencesList(
- ViewGroup parent, View child, ListView list, boolean ignoreSidePadding) {
- list.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
- list.setClipToPadding(false);
- prepareCustomPreferencesList(parent, child, list, ignoreSidePadding);
- }
-
/**
* Prepare a custom preferences layout, moving padding to {@link ListView}
* when outside scrollbars are requested. Usually used to display
diff --git a/src/com/android/settings/applications/ClearDefaultsPreference.java b/src/com/android/settings/applications/ClearDefaultsPreference.java
index e9c5a0e..0de2676 100644
--- a/src/com/android/settings/applications/ClearDefaultsPreference.java
+++ b/src/com/android/settings/applications/ClearDefaultsPreference.java
@@ -24,6 +24,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.SpannableString;
@@ -68,7 +69,9 @@
}
public ClearDefaultsPreference(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
+ this(context, attrs, TypedArrayUtils.getAttr(context,
+ android.support.v7.preference.R.attr.preferenceStyle,
+ android.R.attr.preferenceStyle));
}
public ClearDefaultsPreference(Context context) {
diff --git a/src/com/android/settings/applications/ExternalSourcesDetails.java b/src/com/android/settings/applications/ExternalSourcesDetails.java
index af9251c..6441437 100644
--- a/src/com/android/settings/applications/ExternalSourcesDetails.java
+++ b/src/com/android/settings/applications/ExternalSourcesDetails.java
@@ -15,6 +15,9 @@
*/
package com.android.settings.applications;
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import android.app.AlertDialog;
@@ -26,6 +29,7 @@
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.settings.R;
+import com.android.settings.Settings;
import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -67,6 +71,10 @@
final boolean checked = (Boolean) newValue;
if (preference == mSwitchPref) {
if (mInstallAppsState != null && checked != mInstallAppsState.canInstallApps()) {
+ if (Settings.ManageAppExternalSourcesActivity.class.getName().equals(
+ getIntent().getComponent().getClassName())) {
+ setResult(checked ? RESULT_OK : RESULT_CANCELED);
+ }
setCanInstallApps(checked);
refreshUi();
}
@@ -97,9 +105,13 @@
protected boolean refreshUi() {
mInstallAppsState = mAppBridge.createInstallAppsStateFor(mPackageName,
mPackageInfo.applicationInfo.uid);
-
- final boolean canWrite = mInstallAppsState.canInstallApps();
- mSwitchPref.setChecked(canWrite);
+ if (!mInstallAppsState.isPotentialAppSource()) {
+ // Invalid app entry. Should not allow changing permission
+ mSwitchPref.setEnabled(false);
+ return true;
+ }
+ final boolean canInstallApps = mInstallAppsState.canInstallApps();
+ mSwitchPref.setChecked(canInstallApps);
return true;
}
diff --git a/src/com/android/settings/bluetooth/BluetoothProgressCategory.java b/src/com/android/settings/bluetooth/BluetoothProgressCategory.java
index a36c98b..ec948e0 100644
--- a/src/com/android/settings/bluetooth/BluetoothProgressCategory.java
+++ b/src/com/android/settings/bluetooth/BluetoothProgressCategory.java
@@ -48,7 +48,6 @@
}
private void init() {
- setIcon(R.drawable.ic_settings_bluetooth);
setEmptyTextRes(R.string.bluetooth_no_devices_found);
}
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 59c5014..2a3c5d3 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -50,6 +50,7 @@
import com.android.settings.applications.AdvancedAppSettings;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.DrawOverlayDetails;
+import com.android.settings.applications.ExternalSourcesDetails;
import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageApplications;
import com.android.settings.applications.ManageDomainUrls;
@@ -214,6 +215,7 @@
ProcessStatsSummary.class.getName(),
DrawOverlayDetails.class.getName(),
WriteSettingsDetails.class.getName(),
+ ExternalSourcesDetails.class.getName(),
AdvancedAppSettings.class.getName(),
WallpaperTypeSettings.class.getName(),
VrListenerSettings.class.getName(),
diff --git a/src/com/android/settings/ZonePicker.java b/src/com/android/settings/datetime/ZonePicker.java
similarity index 89%
rename from src/com/android/settings/ZonePicker.java
rename to src/com/android/settings/datetime/ZonePicker.java
index f6d6a6c..2d58dd8 100644
--- a/src/com/android/settings/ZonePicker.java
+++ b/src/com/android/settings/datetime/ZonePicker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.datetime;
import android.annotation.NonNull;
import android.app.Activity;
@@ -33,8 +33,9 @@
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
+import com.android.settings.R;
import com.android.settings.core.instrumentation.Instrumentable;
+import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
import com.android.settingslib.datetime.ZoneGetter;
import java.util.Collections;
@@ -52,11 +53,6 @@
*/
public class ZonePicker extends ListFragment implements Instrumentable {
- public interface ZoneSelectionListener {
- // You can add any argument if you really need it...
- void onZoneSelected(TimeZone tz);
- }
-
private static final int MENU_TIMEZONE = Menu.FIRST+1;
private static final int MENU_ALPHABETICAL = Menu.FIRST;
private final VisibilityLoggerMixin mVisibilityLoggerMixin =
@@ -67,8 +63,6 @@
private SimpleAdapter mTimezoneSortedAdapter;
private SimpleAdapter mAlphabeticalAdapter;
- private ZoneSelectionListener mListener;
-
/**
* Constructs an adapter with TimeZone list. Sorted by TimeZone in default.
*
@@ -148,15 +142,6 @@
return -1;
}
- /**
- * @param item one of items in adapters. The adapter should be constructed by
- * {@link #constructTimezoneAdapter(Context, boolean)}.
- * @return TimeZone object corresponding to the item.
- */
- public static TimeZone obtainTimeZoneFromItem(Object item) {
- return TimeZone.getTimeZone((String)((Map<?, ?>)item).get(ZoneGetter.KEY_ID));
- }
-
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -185,8 +170,8 @@
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = super.onCreateView(inflater, container, savedInstanceState);
- final ListView list = (ListView) view.findViewById(android.R.id.list);
- Utils.forcePrepareCustomPreferencesList(container, view, list, false);
+ final ListView list = view.findViewById(android.R.id.list);
+ prepareCustomPreferencesList(list);
return view;
}
@@ -233,8 +218,10 @@
}
}
- public void setZoneSelectionListener(ZoneSelectionListener listener) {
- mListener = listener;
+ static void prepareCustomPreferencesList(ListView list) {
+ list.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
+ list.setClipToPadding(false);
+ list.setDivider(null);
}
private void setSorting(boolean sortByTimezone) {
@@ -259,12 +246,9 @@
final Activity activity = getActivity();
final AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE);
alarm.setTimeZone(tzId);
- final TimeZone tz = TimeZone.getTimeZone(tzId);
- if (mListener != null) {
- mListener.onZoneSelected(tz);
- } else {
- getActivity().onBackPressed();
- }
+
+ getActivity().onBackPressed();
+
}
@Override
diff --git a/src/com/android/settings/display/ThemePreferenceController.java b/src/com/android/settings/display/ThemePreferenceController.java
index e66e7ce..a8d47d6 100644
--- a/src/com/android/settings/display/ThemePreferenceController.java
+++ b/src/com/android/settings/display/ThemePreferenceController.java
@@ -15,15 +15,19 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_THEME;
-import android.app.AlertDialog;
-import android.app.UiModeManager;
import android.content.Context;
-import android.content.DialogInterface.OnClickListener;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
-
import android.text.TextUtils;
+
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
@@ -31,17 +35,27 @@
import libcore.util.Objects;
+import java.util.List;
+
public class ThemePreferenceController extends PreferenceController implements
Preference.OnPreferenceChangeListener {
private static final String KEY_THEME = "theme";
- private final UiModeManager mUiModeManager;
private final MetricsFeatureProvider mMetricsFeatureProvider;
+ private final OverlayManager mOverlayService;
+ private final PackageManager mPackageManager;
public ThemePreferenceController(Context context) {
+ this(context, ServiceManager.getService(Context.OVERLAY_SERVICE) != null
+ ? new OverlayManager() : null);
+ }
+
+ @VisibleForTesting
+ ThemePreferenceController(Context context, OverlayManager overlayManager) {
super(context);
- mUiModeManager = context.getSystemService(UiModeManager.class);
+ mOverlayService = overlayManager;
+ mPackageManager = context.getPackageManager();
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
@@ -61,12 +75,18 @@
@Override
public void updateState(Preference preference) {
ListPreference pref = (ListPreference) preference;
- String[] options = getAvailableThemes();
- for (int i = 0; i < options.length; i++) {
- options[i] = nullToDefault(options[i]);
+ String[] pkgs = getAvailableThemes();
+ CharSequence[] labels = new CharSequence[pkgs.length];
+ for (int i = 0; i < pkgs.length; i++) {
+ try {
+ labels[i] = mPackageManager.getApplicationInfo(pkgs[i], 0)
+ .loadLabel(mPackageManager);
+ } catch (NameNotFoundException e) {
+ labels[i] = pkgs[i];
+ }
}
- pref.setEntries(options);
- pref.setEntryValues(options);
+ pref.setEntries(labels);
+ pref.setEntryValues(pkgs);
String theme = getCurrentTheme();
if (TextUtils.isEmpty(theme)) {
theme = mContext.getString(R.string.default_theme);
@@ -77,49 +97,76 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (Objects.equal(newValue, mUiModeManager.getTheme())) {
+ String current = getTheme();
+ if (Objects.equal(newValue, current)) {
return true;
}
- // TODO: STOPSHIP Don't require reboot and remove this prompt.
- OnClickListener onConfirm = (d, i) -> {
- mUiModeManager.setTheme(defaultToNull((String) newValue));
- ((ListPreference) preference).setValue((String) newValue);
- };
- new AlertDialog.Builder(mContext)
- .setTitle(R.string.change_theme_reboot)
- .setPositiveButton(com.android.internal.R.string.global_action_restart, onConfirm)
- .setNegativeButton(android.R.string.cancel, null)
- .show();
- return false;
+ try {
+ mOverlayService.setEnabledExclusive((String) newValue, true, UserHandle.myUserId());
+ } catch (RemoteException e) {
+ return false;
+ }
+ return true;
+ }
+
+ private String getTheme() {
+ try {
+ List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
+ UserHandle.myUserId());
+ for (int i = 0, size = infos.size(); i < size; i++) {
+ if (infos.get(i).isEnabled()) {
+ return infos.get(i).packageName;
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ return null;
}
@Override
public boolean isAvailable() {
+ if (mOverlayService == null) return false;
String[] themes = getAvailableThemes();
return themes != null && themes.length > 1;
}
+
@VisibleForTesting
String getCurrentTheme() {
- return mUiModeManager.getTheme();
+ return getTheme();
}
@VisibleForTesting
String[] getAvailableThemes() {
- return mUiModeManager.getAvailableThemes();
+ try {
+ List<OverlayInfo> infos = mOverlayService.getOverlayInfosForTarget("android",
+ UserHandle.myUserId());
+ String[] pkgs = new String[infos.size()];
+ for (int i = 0, size = infos.size(); i < size; i++) {
+ pkgs[i] = infos.get(i).packageName;
+ }
+ return pkgs;
+ } catch (RemoteException e) {
+ }
+ return new String[0];
}
- private String nullToDefault(String input) {
- if (TextUtils.isEmpty(input)) {
- return mContext.getString(R.string.default_theme);
- }
- return input;
- }
+ public static class OverlayManager {
+ private final IOverlayManager mService;
- private String defaultToNull(String input) {
- if (mContext.getString(R.string.default_theme).equals(input)) {
- return null;
+ public OverlayManager() {
+ mService = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
}
- return input;
+
+ public void setEnabledExclusive(String pkg, boolean enabled, int userId)
+ throws RemoteException {
+ mService.setEnabledExclusive(pkg, enabled, userId);
+ }
+
+ public List<OverlayInfo> getOverlayInfosForTarget(String target, int userId)
+ throws RemoteException {
+ return mService.getOverlayInfosForTarget(target, userId);
+ }
}
}
diff --git a/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java b/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
index 6b72573..f6bd4c1 100644
--- a/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
+++ b/src/com/android/settings/enterprise/AdminActionPreferenceControllerBase.java
@@ -40,7 +40,7 @@
public void updateState(Preference preference) {
final Date timestamp = getAdminActionTimestamp();
preference.setSummary(timestamp == null ?
- mContext.getString(R.string.enterprise_privacy_never) :
+ mContext.getString(R.string.enterprise_privacy_none) :
DateUtils.formatDateTime(mContext, timestamp.getTime(),
DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE));
}
diff --git a/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceController.java b/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceController.java
index a2137ff..35648c8 100644
--- a/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceController.java
+++ b/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceController.java
@@ -17,8 +17,6 @@
import android.Manifest;
import android.content.Context;
-import com.android.settings.R;
-
public class AdminGrantedCameraPermissionPreferenceController extends
AdminGrantedPermissionsPreferenceControllerBase {
@@ -26,8 +24,7 @@
= "enterprise_privacy_number_camera_access_packages";
public AdminGrantedCameraPermissionPreferenceController(Context context) {
- super(context, new String[] {Manifest.permission.CAMERA},
- R.plurals.enterprise_privacy_number_camera_access_packages);
+ super(context, new String[] {Manifest.permission.CAMERA});
}
@Override
diff --git a/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceController.java b/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceController.java
index 0453b53..f570558 100644
--- a/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceController.java
+++ b/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceController.java
@@ -17,8 +17,6 @@
import android.Manifest;
import android.content.Context;
-import com.android.settings.R;
-
public class AdminGrantedLocationPermissionsPreferenceController extends
AdminGrantedPermissionsPreferenceControllerBase {
@@ -27,8 +25,7 @@
public AdminGrantedLocationPermissionsPreferenceController(Context context) {
super(context, new String[] {Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION},
- R.plurals.enterprise_privacy_number_location_access_packages);
+ Manifest.permission.ACCESS_FINE_LOCATION});
}
@Override
diff --git a/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceController.java b/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceController.java
index 3adde92..842235d 100644
--- a/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceController.java
+++ b/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceController.java
@@ -17,8 +17,6 @@
import android.Manifest;
import android.content.Context;
-import com.android.settings.R;
-
public class AdminGrantedMicrophonePermissionPreferenceController extends
AdminGrantedPermissionsPreferenceControllerBase {
@@ -26,8 +24,7 @@
= "enterprise_privacy_number_microphone_access_packages";
public AdminGrantedMicrophonePermissionPreferenceController(Context context) {
- super(context, new String[] {Manifest.permission.RECORD_AUDIO},
- R.plurals.enterprise_privacy_number_microphone_access_packages);
+ super(context, new String[] {Manifest.permission.RECORD_AUDIO});
}
@Override
diff --git a/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBase.java b/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBase.java
index 2ca5451..2b972a5 100644
--- a/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBase.java
+++ b/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBase.java
@@ -18,6 +18,7 @@
import android.content.res.Resources;
import android.support.v7.preference.Preference;
+import com.android.settings.R;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.PreferenceController;
import com.android.settings.overlay.FeatureFactory;
@@ -25,14 +26,11 @@
public abstract class AdminGrantedPermissionsPreferenceControllerBase extends PreferenceController {
private final String[] mPermissions;
- private final int mStringResourceId;
private final ApplicationFeatureProvider mFeatureProvider;
- public AdminGrantedPermissionsPreferenceControllerBase(Context context, String[] permissions,
- int stringResourceId) {
+ public AdminGrantedPermissionsPreferenceControllerBase(Context context, String[] permissions) {
super(context);
mPermissions = permissions;
- mStringResourceId = stringResourceId;
mFeatureProvider = FeatureFactory.getFactory(context)
.getApplicationFeatureProvider(context);
}
@@ -45,8 +43,8 @@
preference.setVisible(false);
} else {
preference.setVisible(true);
- preference.setTitle(mContext.getResources().getQuantityString(
- mStringResourceId, num, num));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_packages, num, num));
}
});
}
diff --git a/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceController.java b/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceController.java
new file mode 100644
index 0000000..c8ea551
--- /dev/null
+++ b/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class CaCertsCurrentUserPreferenceController extends PreferenceController {
+
+ private static final String CA_CERTS_CURRENT_USER = "ca_certs_current_user";
+ private final EnterprisePrivacyFeatureProvider mFeatureProvider;
+
+ public CaCertsCurrentUserPreferenceController(Context context) {
+ super(context);
+ mFeatureProvider = FeatureFactory.getFactory(context)
+ .getEnterprisePrivacyFeatureProvider(context);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int certs = mFeatureProvider.getNumberOfOwnerInstalledCaCertsInCurrentUser();
+ if (certs == 0) {
+ preference.setVisible(false);
+ return;
+ }
+ preference.setTitle(mContext.getResources().getQuantityString(
+ mFeatureProvider.isInCompMode() ? R.plurals.enterprise_privacy_ca_certs_personal :
+ R.plurals.enterprise_privacy_ca_certs_user, certs));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_ca_certs, certs, certs));
+ preference.setVisible(true);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return CA_CERTS_CURRENT_USER;
+ }
+}
diff --git a/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceController.java b/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceController.java
new file mode 100644
index 0000000..33224ae
--- /dev/null
+++ b/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceController.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class CaCertsManagedProfilePreferenceController extends PreferenceController {
+
+ private static final String KEY_CA_CERTS_MANAGED_PROFILE = "ca_certs_managed_profile";
+ private final EnterprisePrivacyFeatureProvider mFeatureProvider;
+
+ public CaCertsManagedProfilePreferenceController(Context context) {
+ super(context);
+ mFeatureProvider = FeatureFactory.getFactory(context)
+ .getEnterprisePrivacyFeatureProvider(context);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int certs = mFeatureProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile();
+ if (certs == 0) {
+ preference.setVisible(false);
+ return;
+ }
+ preference.setTitle(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_ca_certs_work, certs));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_ca_certs, certs, certs));
+ preference.setVisible(true);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_CA_CERTS_MANAGED_PROFILE;
+ }
+}
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
index 29f315c..7fae8bb 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapper.java
@@ -16,10 +16,13 @@
package com.android.settings.enterprise;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.os.UserHandle;
import android.support.annotation.Nullable;
+import java.util.List;
+
/**
* This interface replicates a subset of the android.app.admin.DevicePolicyManager (DPM). The
* interface exists so that we can use a thin wrapper around the DPM in production code and a mock
@@ -97,4 +100,12 @@
* @see android.app.admin.DevicePolicyManager#isCurrentInputMethodSetByOwner
*/
boolean isCurrentInputMethodSetByOwner();
+
+
+ /**
+ * Calls {@code DevicePolicyManager.getOwnerInstalledCaCerts()}.
+ *
+ * @see android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts
+ */
+ List<String> getOwnerInstalledCaCerts(@NonNull UserHandle user);
}
diff --git a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
index 0fdcb9c..76264b4 100644
--- a/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
+++ b/src/com/android/settings/enterprise/DevicePolicyManagerWrapperImpl.java
@@ -16,11 +16,14 @@
package com.android.settings.enterprise;
+import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.os.UserHandle;
import android.support.annotation.Nullable;
+import java.util.List;
+
public class DevicePolicyManagerWrapperImpl implements DevicePolicyManagerWrapper {
private final DevicePolicyManager mDpm;
@@ -78,4 +81,9 @@
public boolean isCurrentInputMethodSetByOwner() {
return mDpm.isCurrentInputMethodSetByOwner();
}
+
+ @Override
+ public List<String> getOwnerInstalledCaCerts(@NonNull UserHandle user) {
+ return mDpm.getOwnerInstalledCaCerts(user);
+ }
}
diff --git a/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceController.java b/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceController.java
index 1fbb04a..9b4be3a 100644
--- a/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceController.java
+++ b/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceController.java
@@ -44,9 +44,8 @@
preference.setVisible(false);
} else {
preference.setVisible(true);
- preference.setTitle(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_enterprise_installed_packages,
- num, num));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_packages, num, num));
}
});
}
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
index 30b74f5..792c3ac 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java
@@ -88,4 +88,16 @@
* Owner or Profile Owner in that user. Otherwise, returns {@code null}.
*/
String getImeLabelIfOwnerSet();
+
+ /**
+ * Returns the number of CA certificates that the Device Owner or Profile Owner installed in
+ * the current user.
+ */
+ int getNumberOfOwnerInstalledCaCertsInCurrentUser();
+
+ /**
+ * Returns the number of CA certificates that the Profile Owner installed in the current user's
+ * managed profile (if any).
+ */
+ int getNumberOfOwnerInstalledCaCertsInManagedProfile();
}
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
index 49d87a5..3b8251c 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java
@@ -178,6 +178,22 @@
}
}
+ @Override
+ public int getNumberOfOwnerInstalledCaCertsInCurrentUser() {
+ final List<String> certs = mDpm.getOwnerInstalledCaCerts(new UserHandle(MY_USER_ID));
+ return certs != null ? certs.size() : 0;
+ }
+
+ @Override
+ public int getNumberOfOwnerInstalledCaCertsInManagedProfile() {
+ final int userId = getManagedProfileUserId();
+ if (userId == UserHandle.USER_NULL) {
+ return 0;
+ }
+ final List<String> certs = mDpm.getOwnerInstalledCaCerts(new UserHandle(userId));
+ return certs != null ? certs.size() : 0;
+ }
+
protected static class EnterprisePrivacySpan extends ClickableSpan {
private final Context mContext;
diff --git a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
index 3929bbd..140a05c 100644
--- a/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
+++ b/src/com/android/settings/enterprise/EnterprisePrivacySettings.java
@@ -63,6 +63,8 @@
controllers.add(new AlwaysOnVpnPrimaryUserPreferenceController(context));
controllers.add(new AlwaysOnVpnManagedProfilePreferenceController(context));
controllers.add(new GlobalHttpProxyPreferenceController(context));
+ controllers.add(new CaCertsCurrentUserPreferenceController(context));
+ controllers.add(new CaCertsManagedProfilePreferenceController(context));
controllers.add(new FailedPasswordWipePrimaryUserPreferenceController(context));
controllers.add(new FailedPasswordWipeManagedProfilePreferenceController(context));
controllers.add(new ImePreferenceController(context));
diff --git a/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceController.java b/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceController.java
index 23627cd..08a72e3 100644
--- a/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceController.java
+++ b/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceController.java
@@ -68,9 +68,8 @@
preference.setVisible(false);
} else {
preference.setVisible(true);
- preference.setTitle(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_enterprise_set_default_apps,
- num, num));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_packages, num, num));
}
}
diff --git a/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceController.java b/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceController.java
index 2eac0a9..5a0e7c8 100644
--- a/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceController.java
+++ b/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceController.java
@@ -15,8 +15,6 @@
import android.content.Context;
-import com.android.settings.R;
-
public class FailedPasswordWipeManagedProfilePreferenceController
extends FailedPasswordWipePreferenceControllerBase {
@@ -24,7 +22,7 @@
= "failed_password_wipe_managed_profile";
public FailedPasswordWipeManagedProfilePreferenceController(Context context) {
- super(context, R.plurals.enterprise_privacy_failed_password_wipe_work);
+ super(context);
}
@Override
diff --git a/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBase.java b/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBase.java
index 7cdd8da..ee4aecf 100644
--- a/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBase.java
+++ b/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBase.java
@@ -18,17 +18,16 @@
import android.content.res.Resources;
import android.support.v7.preference.Preference;
+import com.android.settings.R;
import com.android.settings.core.PreferenceController;
import com.android.settings.overlay.FeatureFactory;
public abstract class FailedPasswordWipePreferenceControllerBase extends PreferenceController {
- private final int mStringResourceId;
protected final EnterprisePrivacyFeatureProvider mFeatureProvider;
- public FailedPasswordWipePreferenceControllerBase(Context context, int stringResourceId) {
+ public FailedPasswordWipePreferenceControllerBase(Context context) {
super(context);
- mStringResourceId = stringResourceId;
mFeatureProvider = FeatureFactory.getFactory(context)
.getEnterprisePrivacyFeatureProvider(context);
}
@@ -42,8 +41,9 @@
preference.setVisible(false);
} else {
preference.setVisible(true);
- preference.setTitle(mContext.getResources().getQuantityString(
- mStringResourceId, failedPasswordsBeforeWipe, failedPasswordsBeforeWipe));
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_failed_password_wipe,
+ failedPasswordsBeforeWipe, failedPasswordsBeforeWipe));
}
}
diff --git a/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java b/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java
index 91bdf9b..44c6383 100644
--- a/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java
+++ b/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceController.java
@@ -15,8 +15,6 @@
import android.content.Context;
-import com.android.settings.R;
-
public class FailedPasswordWipePrimaryUserPreferenceController
extends FailedPasswordWipePreferenceControllerBase {
@@ -24,7 +22,7 @@
= "failed_password_wipe_primary_user";
public FailedPasswordWipePrimaryUserPreferenceController(Context context) {
- super(context, R.plurals.enterprise_privacy_failed_password_wipe_device);
+ super(context);
}
@Override
diff --git a/src/com/android/settings/enterprise/ImePreferenceController.java b/src/com/android/settings/enterprise/ImePreferenceController.java
index 18dfac7..3c0cc26 100644
--- a/src/com/android/settings/enterprise/ImePreferenceController.java
+++ b/src/com/android/settings/enterprise/ImePreferenceController.java
@@ -40,8 +40,8 @@
preference.setVisible(false);
return;
}
- preference.setTitle(mContext.getResources().getString(
- R.string.enterprise_privacy_input_method, ownerSetIme));
+ preference.setSummary(mContext.getResources().getString(
+ R.string.enterprise_privacy_input_method_name, ownerSetIme));
preference.setVisible(true);
}
diff --git a/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
index 91ac4c2..4252429 100644
--- a/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
+++ b/src/com/android/settings/enterprise/InstalledPackagesPreferenceController.java
@@ -24,7 +24,7 @@
public class InstalledPackagesPreferenceController extends PreferenceController {
- private static final String KEY_NUMBER_INSTALLED_PACKAGES = "number_installed_packages";
+ private static final String KEY_INSTALLED_PACKAGES = "installed_packages";
private final ApplicationFeatureProvider mFeatureProvider;
public InstalledPackagesPreferenceController(Context context) {
@@ -38,8 +38,12 @@
mFeatureProvider.calculateNumberOfInstalledApps(
ApplicationFeatureProvider.IGNORE_INSTALL_REASON,
(num) -> {
- preference.setTitle(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_installed_packages, num, num));
+ if (num == 0) {
+ preference.setSummary("");
+ } else {
+ preference.setSummary(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_packages, num, num));
+ }
});
}
@@ -50,6 +54,6 @@
@Override
public String getPreferenceKey() {
- return KEY_NUMBER_INSTALLED_PACKAGES;
+ return KEY_INSTALLED_PACKAGES;
}
}
diff --git a/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
new file mode 100644
index 0000000..0f08398
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceController.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.util.Log;
+import com.android.settings.core.PreferenceController;
+
+/**
+ * Controller to control whether an app can run in the background
+ */
+public class BackgroundActivityPreferenceController extends PreferenceController implements
+ Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "BgActivityPrefContr";
+ private static final String KEY_BACKGROUND_ACTIVITY = "background_activity";
+
+ private final PackageManager mPackageManager;
+ private final AppOpsManager mAppOpsManager;
+ private final String[] mPackages;
+ private final int mUid;
+
+ private String mTargetPackage;
+
+ public BackgroundActivityPreferenceController(Context context, int uid) {
+ super(context);
+ mPackageManager = context.getPackageManager();
+ mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mUid = uid;
+ mPackages = mPackageManager.getPackagesForUid(mUid);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int mode = mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage);
+
+ if (mode == AppOpsManager.MODE_ERRORED) {
+ preference.setEnabled(false);
+ } else {
+ ((SwitchPreference) preference).setChecked(mode != AppOpsManager.MODE_IGNORED);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (mPackages == null) {
+ return false;
+ }
+ for (final String packageName : mPackages) {
+ if (isLegacyApp(packageName)) {
+ mTargetPackage = packageName;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_BACKGROUND_ACTIVITY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean switchOn = (Boolean) newValue;
+ mAppOpsManager.setUidMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid,
+ switchOn ? AppOpsManager.MODE_DEFAULT : AppOpsManager.MODE_IGNORED);
+
+ return true;
+ }
+
+ @VisibleForTesting
+ boolean isLegacyApp(final String packageName) {
+ try {
+ ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
+ PackageManager.GET_META_DATA);
+
+ return info.targetSdkVersion < Build.VERSION_CODES.O;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Cannot find package: " + packageName, e);
+ }
+
+ return false;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
index 94fc3b5..956b279 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java
@@ -34,7 +34,6 @@
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
-import android.provider.SearchIndexableResource;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -67,7 +66,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
public class PowerUsageDetail extends PowerUsageBase implements Button.OnClickListener {
@@ -396,7 +395,11 @@
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
- return null;
+ final List<PreferenceController> controllers = new ArrayList<>();
+ final int uid = getArguments().getInt(EXTRA_UID, 0);
+ controllers.add(new BackgroundActivityPreferenceController(context, uid));
+
+ return controllers;
}
@Override
diff --git a/src/com/android/settings/network/NetworkScoreManagerWrapper.java b/src/com/android/settings/network/NetworkScoreManagerWrapper.java
index 0d35378..3489640 100644
--- a/src/com/android/settings/network/NetworkScoreManagerWrapper.java
+++ b/src/com/android/settings/network/NetworkScoreManagerWrapper.java
@@ -56,6 +56,13 @@
return mNetworkScoreManager.getActiveScorerPackage();
}
+ /**
+ * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
+ */
+ @Nullable
+ public NetworkScorerAppData getActiveScorer() {
+ return mNetworkScoreManager.getActiveScorer();
+ }
/**
* Set the active scorer to a new package and clear existing scores.
diff --git a/src/com/android/settings/network/NetworkScorerPicker.java b/src/com/android/settings/network/NetworkScorerPicker.java
index da9d84f..2d04e56 100644
--- a/src/com/android/settings/network/NetworkScorerPicker.java
+++ b/src/com/android/settings/network/NetworkScorerPicker.java
@@ -26,9 +26,9 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.core.instrumentation.Instrumentable;
import com.android.settings.widget.RadioButtonPreference;
import java.util.List;
@@ -43,8 +43,7 @@
@Override
public int getMetricsCategory() {
- //TODO(35854268): Add logging.
- return Instrumentable.METRICS_CATEGORY_UNKNOWN;
+ return MetricsProto.MetricsEvent.SETTINGS_NETWORK_SCORER;
}
@Override
diff --git a/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java b/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java
new file mode 100644
index 0000000..6ff6edb
--- /dev/null
+++ b/src/com/android/settings/network/NetworkScorerPickerPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.network;
+
+import android.content.Context;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceController;
+
+/**
+ * {@link PreferenceController} that shows the active network scorer and toggles the preference
+ * based on {@link Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED}.
+ */
+public class NetworkScorerPickerPreferenceController extends PreferenceController {
+
+ private static final String KEY_NETWORK_SCORER_PICKER = "network_scorer_picker";
+
+ private final NetworkScoreManagerWrapper mNetworkScoreManager;
+
+ public NetworkScorerPickerPreferenceController(Context context,
+ NetworkScoreManagerWrapper networkScoreManager) {
+ super(context);
+ mNetworkScoreManager = networkScoreManager;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_NETWORK_SCORER_PICKER;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1;
+ preference.setEnabled(enabled);
+ if (!enabled) {
+ preference.setSummary(null);
+ return;
+ }
+
+ NetworkScorerAppData scorer = mNetworkScoreManager.getActiveScorer();
+ if (scorer == null) {
+ preference.setSummary(mContext.getString(
+ R.string.network_scorer_picker_none_preference));
+ } else {
+ preference.setSummary(scorer.getRecommendationServiceLabel());
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationStation.java b/src/com/android/settings/notification/NotificationStation.java
index 50bcd95..a357846 100644
--- a/src/com/android/settings/notification/NotificationStation.java
+++ b/src/com/android/settings/notification/NotificationStation.java
@@ -16,8 +16,11 @@
package com.android.settings.notification;
-import android.app.*;
+import android.app.Activity;
+import android.app.ActivityManager;
import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
@@ -26,7 +29,12 @@
import android.content.res.Resources;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.os.*;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -45,13 +53,15 @@
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.CopyablePreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import java.lang.StringBuilder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
public class NotificationStation extends SettingsPreferenceFragment {
private static final String TAG = NotificationStation.class.getSimpleName();
@@ -533,7 +543,7 @@
return null;
}
- private static class HistoricalNotificationPreference extends CopyablePreference {
+ private static class HistoricalNotificationPreference extends Preference {
private final HistoricalNotificationInfo mInfo;
public HistoricalNotificationPreference(Context context, HistoricalNotificationInfo info) {
@@ -574,14 +584,6 @@
}
@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));
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 362a9c4..561c2c6 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -166,7 +166,7 @@
R.drawable.ic_settings_notifications);
addIndex(SystemDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_settings_about);
addIndex(StorageDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_settings_storage);
- addIndex(ConnectedDeviceDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_bt_laptop);
+ addIndex(ConnectedDeviceDashboardFragment.class, NO_DATA_RES_ID, R.drawable.ic_devices_other);
addIndex(EnterprisePrivacySettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_about);
addIndex(PaymentSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_nfc_payment);
addIndex(
diff --git a/src/com/android/settings/search2/SearchFeatureProviderImpl.java b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
index b161686..cd9c470 100644
--- a/src/com/android/settings/search2/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
@@ -40,7 +40,7 @@
@Override
public boolean isEnabled(Context context) {
- return false;
+ return true;
}
@Override
diff --git a/src/com/android/settings/security/SecurityFeatureProviderImpl.java b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
index 2d782a6..7be2d66 100644
--- a/src/com/android/settings/security/SecurityFeatureProviderImpl.java
+++ b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
@@ -46,9 +46,24 @@
private TrustAgentManager mTrustAgentManager;
+ @VisibleForTesting
+ static final Drawable DEFAULT_ICON = null;
+ @VisibleForTesting
+ static final String DEFAULT_SUMMARY = " ";
+
/** Update preferences with data from associated tiles. */
public void updatePreferences(final Context context, final PreferenceScreen preferenceScreen,
final DashboardCategory dashboardCategory) {
+ if (preferenceScreen == null) {
+ return;
+ }
+ int tilesCount = (dashboardCategory != null) ? dashboardCategory.getTilesCount() : 0;
+ if (tilesCount == 0) {
+ return;
+ }
+
+ initPreferences(context, preferenceScreen, dashboardCategory);
+
// Fetching the summary and icon from the provider introduces latency, so do this on a
// separate thread.
Executors.newSingleThreadExecutor().execute(new Runnable() {
@@ -60,16 +75,33 @@
}
@VisibleForTesting
+ static void initPreferences(Context context, PreferenceScreen preferenceScreen,
+ DashboardCategory dashboardCategory) {
+ int tilesCount = (dashboardCategory != null) ? dashboardCategory.getTilesCount() : 0;
+ for (int i = 0; i < tilesCount; i++) {
+ Tile tile = dashboardCategory.getTile(i);
+ // If the tile does not have a key or appropriate meta data, skip it.
+ if (TextUtils.isEmpty(tile.key) || (tile.metaData == null)) {
+ continue;
+ }
+ Preference matchingPref = preferenceScreen.findPreference(tile.key);
+ // If the tile does not have a matching preference, skip it.
+ if (matchingPref == null) {
+ continue;
+ }
+ // Remove any icons that may be loaded before we inject the final icon.
+ matchingPref.setIcon(DEFAULT_ICON);
+ // Reserve room for the summary. This prevents the title from having to shift when the
+ // final title is injected.
+ matchingPref.setSummary(DEFAULT_SUMMARY);
+ }
+ }
+
+ @VisibleForTesting
void updatePreferencesToRunOnWorkerThread(Context context, PreferenceScreen preferenceScreen,
DashboardCategory dashboardCategory) {
- if (preferenceScreen == null) {
- return;
- }
int tilesCount = (dashboardCategory != null) ? dashboardCategory.getTilesCount() : 0;
- if (tilesCount == 0) {
- return;
- }
Map<String, IContentProvider> providerMap = new ArrayMap<>();
for (int i = 0; i < tilesCount; i++) {
Tile tile = dashboardCategory.getTile(i);
diff --git a/src/com/android/settings/widget/FooterPreference.java b/src/com/android/settings/widget/FooterPreference.java
index 4a0d128..9cb9e11 100644
--- a/src/com/android/settings/widget/FooterPreference.java
+++ b/src/com/android/settings/widget/FooterPreference.java
@@ -17,6 +17,7 @@
package com.android.settings.widget;
import android.content.Context;
+import android.support.v4.content.res.TypedArrayUtils;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.method.LinkMovementMethod;
@@ -34,36 +35,24 @@
static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
static final String KEY_FOOTER = "footer_preference";
- public FooterPreference(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- public FooterPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
public FooterPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
+ super(context, attrs, TypedArrayUtils.getAttr(
+ context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
init();
}
public FooterPreference(Context context) {
- super(context);
- init();
+ this(context, null);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
- TextView title = (TextView) holder.itemView.findViewById(android.R.id.title);
+ TextView title = holder.itemView.findViewById(android.R.id.title);
title.setMovementMethod(new LinkMovementMethod());
}
private void init() {
- setLayoutResource(R.layout.preference_footer);
setIcon(R.drawable.ic_info_outline_24dp);
setKey(KEY_FOOTER);
setOrder(ORDER_FOOTER);
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index 18cc28b..78e869b 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -15,16 +15,21 @@
*/
package com.android.settings.wifi;
+import static android.content.Context.NETWORK_SCORE_SERVICE;
import static android.content.Context.WIFI_SERVICE;
import android.content.Context;
+import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.core.PreferenceController;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.network.NetworkScoreManagerWrapper;
+import com.android.settings.network.NetworkScorerPickerPreferenceController;
import com.android.settings.network.WifiCallingPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
@@ -54,6 +59,7 @@
public void onAttach(Context context) {
super.onAttach(context);
mProgressiveDisclosureMixin.setTileLimit(2);
+ ((SettingsActivity) getActivity()).setDisplaySearchMenu(true);
}
@Override
@@ -69,6 +75,9 @@
controllers.add(new CellularFallbackPreferenceController(context));
controllers.add(new NotifyOpenNetworksPreferenceController(context, getLifecycle()));
controllers.add(new WifiWakeupPreferenceController(context, getLifecycle()));
+ controllers.add(new NetworkScorerPickerPreferenceController(context,
+ new NetworkScoreManagerWrapper(
+ (NetworkScoreManager) getSystemService(NETWORK_SCORE_SERVICE))));
controllers.add(new WifiSleepPolicyPreferenceController(context));
controllers.add(new WifiP2pPreferenceController(context, getLifecycle(), mWifiManager));
controllers.add(new WifiCallingPreferenceController(context));
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 9405e8c..8a3c8ac 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -48,7 +48,6 @@
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
-import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
@@ -93,7 +92,6 @@
/* package */ static final int MENU_ID_WPS_PBC = Menu.FIRST;
private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
- private static final int MENU_ID_SCAN = Menu.FIRST + 5;
private static final int MENU_ID_CONNECT = Menu.FIRST + 6;
private static final int MENU_ID_FORGET = Menu.FIRST + 7;
private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
@@ -166,8 +164,6 @@
private Preference mSavedNetworksPreference;
private LinkablePreference mStatusMessagePreference;
- private MenuItem mScanMenuItem;
-
// For Search
private static final String DATA_KEY_REFERENCE = "main_toggle_wifi";
@@ -372,26 +368,6 @@
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- // If the user is not allowed to configure wifi, do not show the menu.
- if (isUiRestricted()) return;
-
- addOptionsMenuItems(menu);
- super.onCreateOptionsMenu(menu, inflater);
- }
-
- /**
- * @param menu
- */
- void addOptionsMenuItems(Menu menu) {
- final boolean wifiIsEnabled = mWifiTracker.isWifiEnabled();
- mScanMenuItem = menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.menu_stats_refresh)
- .setIcon(com.android.internal.R.drawable.ic_menu_refresh);
- mScanMenuItem.setEnabled(wifiIsEnabled)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- }
-
- @Override
public int getMetricsCategory() {
return MetricsEvent.WIFI;
}
@@ -443,10 +419,6 @@
case MENU_ID_WPS_PIN:
showDialog(WPS_PIN_DIALOG_ID);
return true;
- case MENU_ID_SCAN:
- mMetricsFeatureProvider.action(getActivity(), MetricsEvent.ACTION_WIFI_FORCE_SCAN);
- mWifiTracker.forceScan();
- return true;
}
return super.onOptionsItemSelected(item);
}
@@ -719,9 +691,6 @@
mAccessPointsPreferenceCategory.addPreference(mSeeAllNetworksPreference);
}
setConfigureWifiSettingsVisibility();
- if (mScanMenuItem != null) {
- mScanMenuItem.setEnabled(true);
- }
break;
case WifiManager.WIFI_STATE_ENABLING:
@@ -739,9 +708,6 @@
setOffMessage();
setConfigureWifiSettingsVisibility();
setProgressBarVisible(false);
- if (mScanMenuItem != null) {
- mScanMenuItem.setEnabled(false);
- }
break;
}
}
diff --git a/tests/app/AndroidManifest.xml b/tests/app/AndroidManifest.xml
index 1c50700..6659e5f 100644
--- a/tests/app/AndroidManifest.xml
+++ b/tests/app/AndroidManifest.xml
@@ -22,6 +22,9 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
+ <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+ <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/app/src/com/android/settings/applications/ExternalSourcesSettingsTest.java b/tests/app/src/com/android/settings/applications/ExternalSourcesSettingsTest.java
new file mode 100644
index 0000000..9114c6f
--- /dev/null
+++ b/tests/app/src/com/android/settings/applications/ExternalSourcesSettingsTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_DEFAULT;
+import static android.app.AppOpsManager.MODE_ERRORED;
+import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.widget.ListView;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ExternalSourcesSettingsTest {
+
+ private static final String TAG = ExternalSourcesSettingsTest.class.getSimpleName();
+ private static final String WM_DISMISS_KEYGUARD_COMMAND = "wm dismiss-keyguard";
+ private static final long START_ACTIVITY_TIMEOUT = 5000;
+
+ private Context mContext;
+ private UiDevice mUiDevice;
+ private PackageManager mPackageManager;
+ private AppOpsManager mAppOpsManager;
+ private List<UserInfo> mProfiles;
+ private String mPackageName;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mPackageName = InstrumentationRegistry.getContext().getPackageName();
+ mPackageManager = mContext.getPackageManager();
+ mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+ mProfiles = mContext.getSystemService(UserManager.class).getProfiles(UserHandle.myUserId());
+ resetAppOpModeForAllProfiles();
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mUiDevice.wakeUp();
+ mUiDevice.executeShellCommand(WM_DISMISS_KEYGUARD_COMMAND);
+ }
+
+ private void resetAppOpModeForAllProfiles() throws Exception {
+ for (UserInfo user : mProfiles) {
+ final int uid = mPackageManager.getPackageUidAsUser(mPackageName, user.id);
+ mAppOpsManager.setMode(OP_REQUEST_INSTALL_PACKAGES, uid, mPackageName, MODE_DEFAULT);
+ }
+ }
+
+ private Intent createManageExternalSourcesListIntent() {
+ final Intent manageExternalSourcesIntent = new Intent();
+ manageExternalSourcesIntent.setAction(Settings.ACTION_MANAGE_EXTERNAL_SOURCES);
+ return manageExternalSourcesIntent;
+ }
+
+ private Intent createManageExternalSourcesAppIntent(String packageName) {
+ final Intent intent = createManageExternalSourcesListIntent();
+ intent.setData(Uri.parse("package:" + packageName));
+ return intent;
+ }
+
+ private String getApplicationLabel(String packageName) throws Exception {
+ final ApplicationInfo info = mPackageManager.getApplicationInfo(packageName, 0);
+ return mPackageManager.getApplicationLabel(info).toString();
+ }
+
+ private UiObject2 findAndVerifySwitchState(boolean checked) {
+ final BySelector switchSelector = By.clazz(Switch.class).res("android:id/switch_widget");
+ final UiObject2 switchPref = mUiDevice.wait(Until.findObject(switchSelector),
+ START_ACTIVITY_TIMEOUT);
+ assertNotNull("Switch not shown", switchPref);
+ assertTrue("Switch in invalid state", switchPref.isChecked() == checked);
+ return switchPref;
+ }
+
+ @Test
+ public void testManageExternalSourcesList() throws Exception {
+ final String testAppLabel = getApplicationLabel(mPackageName);
+
+ mContext.startActivity(createManageExternalSourcesListIntent());
+ final BySelector preferenceListSelector = By.clazz(ListView.class).res("android:id/list");
+ final UiObject2 preferenceList = mUiDevice.wait(Until.findObject(preferenceListSelector),
+ START_ACTIVITY_TIMEOUT);
+ assertNotNull("App list not shown", preferenceList);
+
+ final BySelector appLabelTextViewSelector = By.clazz(TextView.class)
+ .res("android:id/title")
+ .text(testAppLabel);
+ List<UiObject2> listOfMatchingTextViews;
+ do {
+ listOfMatchingTextViews = preferenceList.findObjects(appLabelTextViewSelector);
+ // assuming the number of profiles will be sufficiently small so that all the entries
+ // for the same package will fit in one screen at some time during the scroll.
+ } while (listOfMatchingTextViews.size() != mProfiles.size() &&
+ preferenceList.scroll(Direction.DOWN, 0.2f));
+ assertEquals("Test app not listed for each profile", mProfiles.size(),
+ listOfMatchingTextViews.size());
+
+ for (UiObject2 matchingObject : listOfMatchingTextViews) {
+ matchingObject.click();
+ findAndVerifySwitchState(true);
+ mUiDevice.pressBack();
+ }
+ }
+
+ private void testAppDetailScreenForAppOp(int appOpMode, int userId) throws Exception {
+ final String testAppLabel = getApplicationLabel(mPackageName);
+ final BySelector appDetailTitleSelector = By.clazz(TextView.class)
+ .res("com.android.settings:id/app_detail_title")
+ .text(testAppLabel);
+
+ mAppOpsManager.setMode(OP_REQUEST_INSTALL_PACKAGES,
+ mPackageManager.getPackageUidAsUser(mPackageName, userId), mPackageName, appOpMode);
+ mContext.startActivityAsUser(createManageExternalSourcesAppIntent(mPackageName),
+ UserHandle.of(userId));
+ mUiDevice.wait(Until.findObject(appDetailTitleSelector), START_ACTIVITY_TIMEOUT);
+ findAndVerifySwitchState(appOpMode == MODE_ALLOWED || appOpMode == MODE_DEFAULT);
+ mUiDevice.pressBack();
+ }
+
+ @Test
+ public void testManageExternalSourcesForApp() throws Exception {
+ // App op MODE_DEFAULT is already tested in #testManageExternalSourcesList
+ for (UserInfo user : mProfiles) {
+ testAppDetailScreenForAppOp(MODE_ALLOWED, user.id);
+ testAppDetailScreenForAppOp(MODE_ERRORED, user.id);
+ }
+ }
+
+ private void testSwitchToggle(int fromAppOp, int toAppOp) throws Exception {
+ final int packageUid = mPackageManager.getPackageUid(mPackageName, 0);
+ final boolean initialState = (fromAppOp == MODE_ALLOWED || fromAppOp == MODE_DEFAULT);
+
+ mAppOpsManager.setMode(OP_REQUEST_INSTALL_PACKAGES, packageUid, mPackageName, fromAppOp);
+ mContext.startActivity(createManageExternalSourcesAppIntent(mPackageName));
+ final UiObject2 switchPref = findAndVerifySwitchState(initialState);
+ switchPref.click();
+ Thread.sleep(1000);
+ assertEquals("Toggling switch did not change app op", toAppOp,
+ mAppOpsManager.checkOpNoThrow(OP_REQUEST_INSTALL_PACKAGES, packageUid,
+ mPackageName));
+ mUiDevice.pressBack();
+ }
+
+ @Test
+ public void testIfSwitchTogglesAppOp() throws Exception {
+ testSwitchToggle(MODE_ALLOWED, MODE_ERRORED);
+ testSwitchToggle(MODE_ERRORED, MODE_ALLOWED);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mUiDevice.pressHome();
+ resetAppOpModeForAllProfiles();
+ }
+}
diff --git a/tests/robotests/src/android/content/om/IOverlayManager.java b/tests/robotests/src/android/content/om/IOverlayManager.java
new file mode 100644
index 0000000..d4f6d10
--- /dev/null
+++ b/tests/robotests/src/android/content/om/IOverlayManager.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package android.content.om;
+
+import android.os.IBinder;
+
+public class IOverlayManager {
+
+ public static class Stub {
+ public static IOverlayManager asInterface(IBinder b) {
+ return null;
+ }
+ }
+}
diff --git a/tests/robotests/src/android/content/om/OverlayInfo.java b/tests/robotests/src/android/content/om/OverlayInfo.java
new file mode 100644
index 0000000..cfd3adc
--- /dev/null
+++ b/tests/robotests/src/android/content/om/OverlayInfo.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package android.content.om;
+
+public class OverlayInfo {
+}
diff --git a/tests/robotests/src/com/android/settings/SettingsActivityTest.java b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
index 68ca890..7822d83 100644
--- a/tests/robotests/src/com/android/settings/SettingsActivityTest.java
+++ b/tests/robotests/src/com/android/settings/SettingsActivityTest.java
@@ -21,6 +21,7 @@
import android.app.FragmentTransaction;
import android.content.Intent;
import android.graphics.Bitmap;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/robotests/src/com/android/settings/ZonePickerTest.java b/tests/robotests/src/com/android/settings/ZonePickerTest.java
index 344eea3..6ab0c2d 100644
--- a/tests/robotests/src/com/android/settings/ZonePickerTest.java
+++ b/tests/robotests/src/com/android/settings/ZonePickerTest.java
@@ -25,6 +25,7 @@
import android.widget.SimpleAdapter;
import android.widget.TextView;
+import com.android.settings.datetime.ZonePicker;
import com.android.settings.testutils.shadow.ShadowLibcoreTimeZoneNames;
import com.android.settings.testutils.shadow.ShadowTimeZoneNames;
diff --git a/tests/robotests/src/com/android/settings/datetime/ZonePickerTest.java b/tests/robotests/src/com/android/settings/datetime/ZonePickerTest.java
new file mode 100644
index 0000000..4acac70
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datetime/ZonePickerTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.datetime;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
+import com.android.settings.testutils.shadow.ShadowZoneGetter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ZonePickerTest {
+
+ private Activity mActivity;
+ private ZonePicker mZonePicker;
+
+ @Before
+ public void setUp() {
+ mActivity = Robolectric.setupActivity(Activity.class);
+ mZonePicker = spy(ZonePicker.class);
+ ReflectionHelpers.setField(mZonePicker, "mVisibilityLoggerMixin",
+ mock(VisibilityLoggerMixin.class));
+ }
+
+ @Test
+ @Config(shadows = ShadowZoneGetter.class)
+ public void testLaunch() {
+ // Shouldn't crash
+ mActivity.getFragmentManager()
+ .beginTransaction()
+ .add(mZonePicker, "test_tag")
+ .commit();
+
+ // Should render
+ verify(mZonePicker).onCreateView(
+ any(LayoutInflater.class),
+ any(ViewGroup.class),
+ any(Bundle.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java
index e3dec76..245d7d6 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/HardwareInfoDialogFragmentTest.java
@@ -31,6 +31,7 @@
import org.robolectric.annotation.Config;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -55,7 +56,11 @@
fragment.show(mActivity.getFragmentManager(), HardwareInfoDialogFragment.TAG);
verify(fragment).setText(
+ any(View.class), eq(R.id.model_label), eq(R.id.model_value),
+ anyString());
+
+ verify(fragment).setText(
any(View.class), eq(R.id.hardware_rev_label), eq(R.id.hardware_rev_value),
- eq(TEST_HARDWARE_REV));
+ anyString());
}
}
diff --git a/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
index fe3e7fd..2c0f4a7 100644
--- a/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -17,10 +17,15 @@
package com.android.settings.display;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.support.v7.preference.ListPreference;
import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.display.ThemePreferenceController.OverlayManager;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,9 +33,13 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -40,24 +49,19 @@
private ListPreference mPreference;
@Mock
private Context mContext;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mApplicationInfo;
private ThemePreferenceController mController;
@Before
- public void setUp() {
+ public void setUp() throws NameNotFoundException {
MockitoAnnotations.initMocks(this);
- mController = spy(new ThemePreferenceController(mContext));
- }
-
- @Test
- public void updateState_nullTheme_shouldSetSummaryToDefault() {
- final String[] themes = {"Theme1", "Theme2"};
- doReturn(null).when(mController).getCurrentTheme();
- doReturn(themes).when(mController).getAvailableThemes();
-
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(mContext.getString(R.string.default_theme));
+ when(mPackageManager.getApplicationInfo(any(), anyInt())).thenReturn(mApplicationInfo);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mController = spy(new ThemePreferenceController(mContext, mock(OverlayManager.class)));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminActionPreferenceControllerTestBase.java b/tests/robotests/src/com/android/settings/enterprise/AdminActionPreferenceControllerTestBase.java
index 59043ed..e9b9d86 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminActionPreferenceControllerTestBase.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminActionPreferenceControllerTestBase.java
@@ -59,12 +59,12 @@
@Test
public void testUpdateState() {
final Preference preference = new Preference(mContext, null, 0, 0);
- when(mContext.getString(R.string.enterprise_privacy_never)).thenReturn("Never");
+ when(mContext.getString(R.string.enterprise_privacy_none)).thenReturn("None");
Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, "24");
setDate(null);
mController.updateState(preference);
- assertThat(preference.getSummary()).isEqualTo("Never");
+ assertThat(preference.getSummary()).isEqualTo("None");
final Date date = new GregorianCalendar(2011 /* year */, 10 /* month */, 9 /* dayOfMonth */,
8 /* hourOfDay */, 7 /* minute */, 6 /* second */).getTime();
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceControllerTest.java
index de24885..6efccfc 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedCameraPermissionPreferenceControllerTest.java
@@ -18,7 +18,6 @@
import android.Manifest;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.runner.RunWith;
@@ -34,8 +33,7 @@
public AdminGrantedCameraPermissionPreferenceControllerTest() {
super("enterprise_privacy_number_camera_access_packages",
- new String[] {Manifest.permission.CAMERA},
- R.plurals.enterprise_privacy_number_camera_access_packages);
+ new String[] {Manifest.permission.CAMERA});
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceControllerTest.java
index 1c6f91d..a23ad8b 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedLocationPermissionsPreferenceControllerTest.java
@@ -18,7 +18,6 @@
import android.Manifest;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.runner.RunWith;
@@ -35,8 +34,7 @@
public AdminGrantedLocationPermissionsPreferenceControllerTest() {
super("enterprise_privacy_number_location_access_packages",
new String[] {Manifest.permission.ACCESS_COARSE_LOCATION,
- Manifest.permission.ACCESS_FINE_LOCATION},
- R.plurals.enterprise_privacy_number_location_access_packages);
+ Manifest.permission.ACCESS_FINE_LOCATION});
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceControllerTest.java
index bcaf63f..39a715f 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedMicrophonePermissionPreferenceControllerTest.java
@@ -18,7 +18,6 @@
import android.Manifest;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.runner.RunWith;
@@ -34,8 +33,7 @@
public AdminGrantedMicrophonePermissionPreferenceControllerTest() {
super("enterprise_privacy_number_microphone_access_packages",
- new String[] {Manifest.permission.RECORD_AUDIO},
- R.plurals.enterprise_privacy_number_microphone_access_packages);
+ new String[] {Manifest.permission.RECORD_AUDIO});
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBaseTest.java
index 2bebbf0..1f52b0e 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerBaseTest.java
@@ -30,7 +30,7 @@
AdminGrantedPermissionsPreferenceControllerTestBase {
public AdminGrantedPermissionsPreferenceControllerBaseTest() {
- super(null, new String[] {"some.permission"}, 123 /* resourceStringId */);
+ super(null, new String[] {"some.permission"});
}
@Override
@@ -43,8 +43,7 @@
AdminGrantedPermissionsPreferenceControllerBase {
AdminGrantedPermissionsPreferenceControllerBaseTestable() {
- super(AdminGrantedPermissionsPreferenceControllerBaseTest.this.mContext, mPermissions,
- mStringResourceId);
+ super(AdminGrantedPermissionsPreferenceControllerBaseTest.this.mContext, mPermissions);
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerTestBase.java b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerTestBase.java
index 68ded37..821fb34 100644
--- a/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerTestBase.java
+++ b/tests/robotests/src/com/android/settings/enterprise/AdminGrantedPermissionsPreferenceControllerTestBase.java
@@ -20,6 +20,7 @@
import android.content.res.Resources;
import android.support.v7.preference.Preference;
+import com.android.settings.R;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -44,7 +45,6 @@
protected final String mKey;
protected final String[] mPermissions;
- protected final int mStringResourceId;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
protected Context mContext;
@@ -52,11 +52,9 @@
protected AdminGrantedPermissionsPreferenceControllerBase mController;
- public AdminGrantedPermissionsPreferenceControllerTestBase(String key, String[] permissions,
- int stringResourceId) {
+ public AdminGrantedPermissionsPreferenceControllerTestBase(String key, String[] permissions) {
mKey = key;
mPermissions = permissions;
- mStringResourceId = stringResourceId;
}
@Before
@@ -83,10 +81,10 @@
preference.setVisible(false);
setNumberOfPackagesWithAdminGrantedPermissions(20);
- when(mContext.getResources().getQuantityString(mStringResourceId, 20, 20))
- .thenReturn("20 packages");
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_packages,
+ 20, 20)).thenReturn("20 packages");
mController.updateState(preference);
- assertThat(preference.getTitle()).isEqualTo("20 packages");
+ assertThat(preference.getSummary()).isEqualTo("20 packages");
assertThat(preference.isVisible()).isTrue();
setNumberOfPackagesWithAdminGrantedPermissions(0);
diff --git a/tests/robotests/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceControllerTest.java
new file mode 100644
index 0000000..3cd63bb
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/CaCertsCurrentUserPreferenceControllerTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import com.android.settings.R;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link CaCertsCurrentUserPreferenceController}.
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class CaCertsCurrentUserPreferenceControllerTest {
+
+ private final String INSTALLED_CERTS_USER_1 = "cert installed";
+ private final String INSTALLED_CERTS_USER_10 = "certs installed";
+ private final String INSTALLED_CERTS_PERSONAL_1 = "cert installed in personal profile";
+ private final String INSTALLED_CERTS_PERSONAL_10 = "certs installed in personal profile";
+ private final String NUMBER_INSTALLED_CERTS_1 = "1 cert";
+ private final String NUMBER_INSTALLED_CERTS_10 = "10 certs";
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ private FakeFeatureFactory mFeatureFactory;
+
+ private CaCertsCurrentUserPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+ mController = new CaCertsCurrentUserPreferenceController(mContext);
+
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_ca_certs_user,
+ 1)).thenReturn(INSTALLED_CERTS_USER_1);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_ca_certs_user,
+ 10)).thenReturn(INSTALLED_CERTS_USER_10);
+ when(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_ca_certs_personal, 1))
+ .thenReturn(INSTALLED_CERTS_PERSONAL_1);
+ when(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_ca_certs_personal, 10))
+ .thenReturn(INSTALLED_CERTS_PERSONAL_10);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_ca_certs,
+ 1, 1)).thenReturn(NUMBER_INSTALLED_CERTS_1);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_ca_certs,
+ 10, 10)).thenReturn(NUMBER_INSTALLED_CERTS_10);
+ }
+
+ @Test
+ public void testUpdateState() {
+ final Preference preference = new Preference(mContext, null, 0, 0);
+ preference.setVisible(true);
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider.isInCompMode()).thenReturn(false);
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(0);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isFalse();
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(1);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_USER_1);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_1);
+
+ preference.setVisible(false);
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(10);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_USER_10);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_10);
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider.isInCompMode()).thenReturn(true);
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(0);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isFalse();
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(1);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_PERSONAL_1);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_1);
+
+ preference.setVisible(false);
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInCurrentUser()).thenReturn(10);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_PERSONAL_10);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_10);
+ }
+
+ @Test
+ public void testIsAvailable() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick() {
+ assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0)))
+ .isFalse();
+ }
+
+ @Test
+ public void testGetPreferenceKey() {
+ assertThat(mController.getPreferenceKey()).isEqualTo("ca_certs_current_user");
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceControllerTest.java
new file mode 100644
index 0000000..c66128b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/enterprise/CaCertsManagedProfilePreferenceControllerTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.enterprise;
+
+import android.content.Context;
+import android.content.res.Resources;
+import com.android.settings.R;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests for {@link CaCertsManagedProfilePreferenceController}.
+ */
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public final class CaCertsManagedProfilePreferenceControllerTest {
+
+ private final String INSTALLED_CERTS_1 = "cert installed";
+ private final String INSTALLED_CERTS_10 = "certs installed";
+ private final String NUMBER_INSTALLED_CERTS_1 = "1 cert";
+ private final String NUMBER_INSTALLED_CERTS_10 = "10 certs";
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ private FakeFeatureFactory mFeatureFactory;
+
+ private CaCertsManagedProfilePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
+ mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+ mController = new CaCertsManagedProfilePreferenceController(mContext);
+
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_ca_certs_work,
+ 1)).thenReturn(INSTALLED_CERTS_1);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_ca_certs_work,
+ 10)).thenReturn(INSTALLED_CERTS_10);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_ca_certs,
+ 1, 1)).thenReturn(NUMBER_INSTALLED_CERTS_1);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_ca_certs,
+ 10, 10)).thenReturn(NUMBER_INSTALLED_CERTS_10);
+ }
+
+ @Test
+ public void testUpdateState() {
+ final Preference preference = new Preference(mContext, null, 0, 0);
+ preference.setVisible(true);
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInManagedProfile()).thenReturn(0);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isFalse();
+
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInManagedProfile()).thenReturn(1);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_1);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_1);
+
+ preference.setVisible(false);
+ when(mFeatureFactory.enterprisePrivacyFeatureProvider
+ .getNumberOfOwnerInstalledCaCertsInManagedProfile()).thenReturn(10);
+ mController.updateState(preference);
+ assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getTitle()).isEqualTo(INSTALLED_CERTS_10);
+ assertThat(preference.getSummary()).isEqualTo(NUMBER_INSTALLED_CERTS_10);
+ }
+
+ @Test
+ public void testIsAvailable() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void testHandlePreferenceTreeClick() {
+ assertThat(mController.handlePreferenceTreeClick(new Preference(mContext, null, 0, 0)))
+ .isFalse();
+ }
+
+ @Test
+ public void testGetPreferenceKey() {
+ assertThat(mController.getPreferenceKey()).isEqualTo("ca_certs_managed_profile");
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceControllerTest.java
index b55b512..46c29b2 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterpriseInstalledPackagesPreferenceControllerTest.java
@@ -86,11 +86,10 @@
assertThat(preference.isVisible()).isFalse();
setNumberOfEnterpriseInstalledPackages(20);
- when(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_enterprise_installed_packages, 20, 20))
- .thenReturn("20 packages");
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_packages,
+ 20, 20)).thenReturn("20 packages");
mController.updateState(preference);
- assertThat(preference.getTitle()).isEqualTo("20 packages");
+ assertThat(preference.getSummary()).isEqualTo("20 packages");
assertThat(preference.isVisible()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
index da9569e..38d9221 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java
@@ -43,6 +43,7 @@
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -255,11 +256,46 @@
assertThat(mProvider.getImeLabelIfOwnerSet()).isEqualTo(IME_PACKAGE_LABEL);
}
+ @Test
+ public void testGetNumberOfOwnerInstalledCaCertsInCurrentUser() {
+ final UserHandle userHandle = new UserHandle(UserHandle.USER_SYSTEM);
+
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(null);
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInCurrentUser()).isEqualTo(0);
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(new ArrayList<String>());
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInCurrentUser()).isEqualTo(0);
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(Arrays.asList(new String[] {"ca1", "ca2"}));
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInCurrentUser()).isEqualTo(2);
+ }
+
+ @Test
+ public void testGetNumberOfOwnerInstalledCaCertsInManagedProfile() {
+ final UserHandle userHandle = new UserHandle(MANAGED_PROFILE_USER_ID);
+ final UserInfo managedProfile =
+ new UserInfo(MANAGED_PROFILE_USER_ID, "", "", UserInfo.FLAG_MANAGED_PROFILE);
+
+ mProfiles.add(managedProfile);
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(null);
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile()).isEqualTo(0);
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(new ArrayList<String>());
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile()).isEqualTo(0);
+ when(mDevicePolicyManager.getOwnerInstalledCaCerts(userHandle))
+ .thenReturn(Arrays.asList(new String[] {"ca1", "ca2"}));
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile()).isEqualTo(2);
+
+ mProfiles.remove(managedProfile);
+ assertThat(mProvider.getNumberOfOwnerInstalledCaCertsInManagedProfile()).isEqualTo(0);
+ }
+
private void resetAndInitializePackageManagerWrapper() {
reset(mPackageManagerWrapper);
when(mPackageManagerWrapper.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
.thenReturn(true);
when(mPackageManagerWrapper.getPackageManager()).thenReturn(mPackageManager);
-
}
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
index f74c63a..2690198 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacySettingsTest.java
@@ -73,7 +73,7 @@
final List<PreferenceController> controllers = mSettings.getPreferenceControllers(
ShadowApplication.getInstance().getApplicationContext());
assertThat(controllers).isNotNull();
- assertThat(controllers.size()).isEqualTo(15);
+ assertThat(controllers.size()).isEqualTo(17);
assertThat(controllers.get(0)).isInstanceOf(InstalledPackagesPreferenceController.class);
assertThat(controllers.get(1)).isInstanceOf(NetworkLogsPreferenceController.class);
assertThat(controllers.get(2)).isInstanceOf(BugReportsPreferenceController.class);
@@ -93,8 +93,13 @@
assertThat(controllers.get(10)).isInstanceOf(
AlwaysOnVpnManagedProfilePreferenceController.class);
assertThat(controllers.get(11)).isInstanceOf(GlobalHttpProxyPreferenceController.class);
- assertThat(controllers.get(12)).isInstanceOf(FailedPasswordWipePrimaryUserPreferenceController.class);
- assertThat(controllers.get(13)).isInstanceOf(FailedPasswordWipeManagedProfilePreferenceController.class);
- assertThat(controllers.get(14)).isInstanceOf(ImePreferenceController.class);
+ assertThat(controllers.get(12)).isInstanceOf(CaCertsCurrentUserPreferenceController.class);
+ assertThat(controllers.get(13)).isInstanceOf(
+ CaCertsManagedProfilePreferenceController.class);
+ assertThat(controllers.get(14)).isInstanceOf(
+ FailedPasswordWipePrimaryUserPreferenceController.class);
+ assertThat(controllers.get(15)).isInstanceOf(
+ FailedPasswordWipeManagedProfilePreferenceController.class);
+ assertThat(controllers.get(16)).isInstanceOf(ImePreferenceController.class);
}
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceControllerTest.java
index 84520a5..093ce20 100644
--- a/tests/robotests/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/EnterpriseSetDefaultAppsPreferenceControllerTest.java
@@ -118,11 +118,10 @@
ContactsContract.Contacts.CONTENT_TYPE)}, 32);
setEnterpriseSetDefaultApps(new Intent[] {new Intent(Intent.ACTION_DIAL),
new Intent(Intent.ACTION_CALL)}, 64);
- when(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_enterprise_set_default_apps, 127, 127))
- .thenReturn("127 apps");
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_packages,
+ 127, 127)).thenReturn("127 apps");
mController.updateState(preference);
- assertThat(preference.getTitle()).isEqualTo("127 apps");
+ assertThat(preference.getSummary()).isEqualTo("127 apps");
assertThat(preference.isVisible()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceControllerTest.java
index 29952a7..c9981f9 100644
--- a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipeManagedProfilePreferenceControllerTest.java
@@ -18,7 +18,6 @@
import android.content.Context;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@@ -38,8 +37,7 @@
private int mMaximumFailedPasswordsBeforeWipe = 0;
public FailedPasswordWipeManagedProfilePreferenceControllerTest() {
- super("failed_password_wipe_managed_profile",
- R.plurals.enterprise_privacy_failed_password_wipe_work);
+ super("failed_password_wipe_managed_profile");
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBaseTest.java b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBaseTest.java
index 97d0d6d..1c7b448 100644
--- a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBaseTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerBaseTest.java
@@ -33,7 +33,7 @@
private int mMaximumFailedPasswordsBeforeWipe = 0;
public FailedPasswordWipePreferenceControllerBaseTest() {
- super(null, 123 /* stringResourceId */);
+ super(null);
}
@Override
@@ -50,7 +50,7 @@
private class FailedPasswordWipePreferenceControllerBaseTestable extends
FailedPasswordWipePreferenceControllerBase {
FailedPasswordWipePreferenceControllerBaseTestable() {
- super(FailedPasswordWipePreferenceControllerBaseTest.this.mContext, mStringResourceId);
+ super(FailedPasswordWipePreferenceControllerBaseTest.this.mContext);
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerTestBase.java b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerTestBase.java
index 5a74fa5..aa189e2 100644
--- a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerTestBase.java
+++ b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePreferenceControllerTestBase.java
@@ -20,6 +20,7 @@
import android.content.res.Resources;
import android.support.v7.preference.Preference;
+import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
@@ -37,7 +38,6 @@
public abstract class FailedPasswordWipePreferenceControllerTestBase {
protected final String mKey;
- protected final int mStringResourceId;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
protected Context mContext;
@@ -45,9 +45,8 @@
protected FailedPasswordWipePreferenceControllerBase mController;
- public FailedPasswordWipePreferenceControllerTestBase(String key, int stringResourceId) {
+ public FailedPasswordWipePreferenceControllerTestBase(String key) {
mKey = key;
- mStringResourceId = stringResourceId;
}
@Before
@@ -65,11 +64,11 @@
preference.setVisible(false);
setMaximumFailedPasswordsBeforeWipe(10);
- when(mContext.getResources().getQuantityString(mStringResourceId, 10, 10))
+ when(mContext.getResources().getQuantityString(
+ R.plurals.enterprise_privacy_number_failed_password_wipe, 10, 10))
.thenReturn("10 attempts");
mController.updateState(preference);
- assertThat(preference.getTitle()).isEqualTo("10 attempts");
- assertThat(preference.isVisible()).isTrue();
+ assertThat(preference.getSummary()).isEqualTo("10 attempts");
setMaximumFailedPasswordsBeforeWipe(0);
mController.updateState(preference);
diff --git a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java
index ea6d977..65c9828 100644
--- a/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/FailedPasswordWipePrimaryUserPreferenceControllerTest.java
@@ -18,7 +18,6 @@
import android.content.Context;
-import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@@ -38,8 +37,7 @@
private int mMaximumFailedPasswordsBeforeWipe = 0;
public FailedPasswordWipePrimaryUserPreferenceControllerTest() {
- super("failed_password_wipe_primary_user",
- R.plurals.enterprise_privacy_failed_password_wipe_device);
+ super("failed_password_wipe_primary_user");
}
@Override
diff --git a/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java
index 232a872..547746c 100644
--- a/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/ImePreferenceControllerTest.java
@@ -44,7 +44,7 @@
public final class ImePreferenceControllerTest {
private final String DEFAULT_IME_LABEL = "Test IME";
- private final String DEFAULT_IME_TEXT = "IME set to Test IME";
+ private final String DEFAULT_IME_TEXT = "Set to Test IME";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@@ -58,7 +58,7 @@
FakeFeatureFactory.setupForTest(mContext);
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mController = new ImePreferenceController(mContext);
- when(mContext.getResources().getString(R.string.enterprise_privacy_input_method,
+ when(mContext.getResources().getString(R.string.enterprise_privacy_input_method_name,
DEFAULT_IME_LABEL)).thenReturn(DEFAULT_IME_TEXT);
}
@@ -76,7 +76,7 @@
.thenReturn(DEFAULT_IME_LABEL);
mController.updateState(preference);
assertThat(preference.isVisible()).isTrue();
- assertThat(preference.getTitle()).isEqualTo(DEFAULT_IME_TEXT);
+ assertThat(preference.getSummary()).isEqualTo(DEFAULT_IME_TEXT);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java
index bf2c4ca..60ceed6 100644
--- a/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/InstalledPackagesPreferenceControllerTest.java
@@ -64,22 +64,30 @@
mController = new InstalledPackagesPreferenceController(mContext);
}
- @Test
- public void testUpdateState() {
- final Preference preference = new Preference(mContext, null, 0, 0);
+ private void setNumberOfInstalledPackages(int number) {
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
((ApplicationFeatureProvider.NumberOfAppsCallback)
- invocation.getArguments()[1]).onNumberOfAppsResult(20);
+ invocation.getArguments()[1]).onNumberOfAppsResult(number);
return null;
}}).when(mFeatureFactory.applicationFeatureProvider)
.calculateNumberOfInstalledApps(
eq(ApplicationFeatureProvider.IGNORE_INSTALL_REASON), anyObject());
- when(mContext.getResources().getQuantityString(
- R.plurals.enterprise_privacy_number_installed_packages, 20, 20))
- .thenReturn("20 packages");
+ }
+
+ @Test
+ public void testUpdateState() {
+ final Preference preference = new Preference(mContext, null, 0, 0);
+
+ setNumberOfInstalledPackages(0);
mController.updateState(preference);
- assertThat(preference.getTitle()).isEqualTo("20 packages");
+ assertThat(preference.getSummary()).isEqualTo("");
+
+ setNumberOfInstalledPackages(20);
+ when(mContext.getResources().getQuantityString(R.plurals.enterprise_privacy_number_packages,
+ 20, 20)).thenReturn("20 packages");
+ mController.updateState(preference);
+ assertThat(preference.getSummary()).isEqualTo("20 packages");
}
@Test
@@ -95,6 +103,6 @@
@Test
public void testGetPreferenceKey() {
- assertThat(mController.getPreferenceKey()).isEqualTo("number_installed_packages");
+ assertThat(mController.getPreferenceKey()).isEqualTo("installed_packages");
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
new file mode 100644
index 0000000..6d3607f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BackgroundActivityPreferenceControllerTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.settings.TestConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BackgroundActivityPreferenceControllerTest {
+ private static final int UID_NORMAL = 1234;
+ private static final int UID_SPECIAL = 2345;
+ private static final String HIGH_SDK_PACKAGE = "com.android.package.high";
+ private static final String LOW_SDK_PACKAGE = "com.android.package.low";
+ private static final String[] PACKAGES_NORMAL = {LOW_SDK_PACKAGE};
+ private static final String[] PACKAGES_SPECIAL = {HIGH_SDK_PACKAGE, LOW_SDK_PACKAGE};
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private AppOpsManager mAppOpsManager;
+ @Mock
+ private SwitchPreference mPreference;
+ @Mock
+ private ApplicationInfo mHighApplicationInfo;
+ @Mock
+ private ApplicationInfo mLowApplicationInfo;
+ private BackgroundActivityPreferenceController mController;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+ when(mPackageManager.getPackagesForUid(UID_NORMAL)).thenReturn(PACKAGES_NORMAL);
+ when(mPackageManager.getPackagesForUid(UID_SPECIAL)).thenReturn(PACKAGES_SPECIAL);
+
+ when(mPackageManager.getApplicationInfo(HIGH_SDK_PACKAGE, PackageManager.GET_META_DATA))
+ .thenReturn(mHighApplicationInfo);
+ when(mPackageManager.getApplicationInfo(LOW_SDK_PACKAGE, PackageManager.GET_META_DATA))
+ .thenReturn(mLowApplicationInfo);
+ mHighApplicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+ mLowApplicationInfo.targetSdkVersion = Build.VERSION_CODES.L;
+
+ mController = new BackgroundActivityPreferenceController(mContext, UID_NORMAL);
+ mController.isAvailable();
+ }
+
+ @Test
+ public void testOnPreferenceChange_TurnOnCheck_MethodInvoked() {
+ mController.onPreferenceChange(mPreference, true);
+
+ verify(mAppOpsManager).setUidMode(AppOpsManager.OP_RUN_IN_BACKGROUND,
+ UID_NORMAL, AppOpsManager.MODE_DEFAULT);
+ }
+
+ @Test
+ public void testOnPreferenceChange_TurnOffCheck_MethodInvoked() {
+ mController.onPreferenceChange(null, false);
+
+ verify(mAppOpsManager).setUidMode(AppOpsManager.OP_RUN_IN_BACKGROUND,
+ UID_NORMAL, AppOpsManager.MODE_IGNORED);
+ }
+
+ @Test
+ public void testUpdateState_CheckOn_SetCheckedTrue() {
+ when(mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
+ .thenReturn(AppOpsManager.MODE_DEFAULT);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(true);
+ }
+
+ @Test
+ public void testUpdateState_CheckOff_SetCheckedFalse() {
+ when(mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_NORMAL, LOW_SDK_PACKAGE))
+ .thenReturn(AppOpsManager.MODE_IGNORED);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setChecked(false);
+ }
+
+ @Test
+ public void testIsPackageAvailable_SdkLowerThanO_ReturnTrue() {
+ assertThat(mController.isLegacyApp(LOW_SDK_PACKAGE)).isTrue();
+ }
+
+ @Test
+ public void testIsPackageAvailable_SdkLargerOrEqualThanO_ReturnFalse() {
+ assertThat(mController.isLegacyApp(HIGH_SDK_PACKAGE)).isFalse();
+ }
+
+ @Test
+ public void testMultiplePackages_ReturnStatusForTargetPackage() {
+ mController = new BackgroundActivityPreferenceController(mContext, UID_SPECIAL);
+ when(mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, LOW_SDK_PACKAGE))
+ .thenReturn(AppOpsManager.MODE_DEFAULT);
+ when(mAppOpsManager
+ .checkOpNoThrow(AppOpsManager.OP_RUN_IN_BACKGROUND, UID_SPECIAL, HIGH_SDK_PACKAGE))
+ .thenReturn(AppOpsManager.MODE_IGNORED);
+
+ final boolean available = mController.isAvailable();
+ mController.updateState(mPreference);
+
+ assertThat(available).isTrue();
+ // Should get status from LOW_SDK_PACKAGE
+ verify(mPreference).setChecked(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
new file mode 100644
index 0000000..6bf47ac
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/NetworkScorerPickerPreferenceControllerTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network;
+
+import static android.provider.Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.net.NetworkScorerAppData;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import com.android.settings.R;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class NetworkScorerPickerPreferenceControllerTest {
+
+ private static final String TEST_SCORER_PACKAGE = "Test Package";
+ private static final String TEST_SCORER_CLASS = "Test Class";
+ private static final String TEST_SCORER_LABEL = "Test Label";
+
+ private Context mContext;
+ @Mock
+ private NetworkScoreManagerWrapper mNetworkScorer;
+ private NetworkScorerPickerPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new NetworkScorerPickerPreferenceController(mContext, mNetworkScorer);
+ }
+
+ @Test
+ public void testIsAvailable_shouldAlwaysReturnTrue() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void updateState_preferenceSetSummaryAsActiveScorerLabel() {
+ Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
+ ComponentName scorer = new ComponentName(TEST_SCORER_PACKAGE, TEST_SCORER_CLASS);
+ NetworkScorerAppData scorerAppData = new NetworkScorerAppData(
+ 0, scorer, TEST_SCORER_LABEL, null /* enableUseOpenWifiActivity */);
+ when(mNetworkScorer.getActiveScorer()).thenReturn(scorerAppData);
+ Preference preference = mock(Preference.class);
+
+ mController.updateState(preference);
+
+ verify(preference).setSummary(TEST_SCORER_LABEL);
+ }
+
+ @Test
+ public void updateState_noActiveScorer_preferenceSetSummaryToNone() {
+ Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
+ when(mNetworkScorer.getActiveScorer()).thenReturn(null);
+ Preference preference = mock(Preference.class);
+
+ mController.updateState(preference);
+
+ verify(preference).setSummary(mContext.getString(
+ R.string.network_scorer_picker_none_preference));
+ }
+
+ @Test
+ public void updateState_networkRecommendationsDisabled_preferenceDisabled() {
+ Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 0);
+ when(mNetworkScorer.getActiveScorer()).thenReturn(null);
+ Preference preference = mock(Preference.class);
+
+ mController.updateState(preference);
+
+ verify(preference).setEnabled(false);
+ verify(preference).setSummary(null);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/SecurityFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/security/SecurityFeatureProviderImplTest.java
index 49eb48b..50debb4 100644
--- a/tests/robotests/src/com/android/settings/security/SecurityFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/security/SecurityFeatureProviderImplTest.java
@@ -171,6 +171,18 @@
verify(screen.findPreference(MOCK_KEY), never()).setSummary(anyString());
}
+ @Test
+ public void initPreferences_shouldLoadDefaults() {
+ PreferenceScreen screen = getPreferenceScreen();
+ DashboardCategory dashboardCategory = getDashboardCategory();
+ dashboardCategory.getTile(0).metaData = new Bundle();
+
+ mImpl.initPreferences(mContext, screen, dashboardCategory);
+ verify(screen.findPreference(MOCK_KEY)).setIcon(SecurityFeatureProviderImpl.DEFAULT_ICON);
+ verify(screen.findPreference(MOCK_KEY))
+ .setSummary(SecurityFeatureProviderImpl.DEFAULT_SUMMARY);
+ }
+
private PreferenceScreen getPreferenceScreen() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final Preference pref = mock(Preference.class);
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowZoneGetter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowZoneGetter.java
new file mode 100644
index 0000000..655acf1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowZoneGetter.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+
+import com.android.settingslib.datetime.ZoneGetter;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+@Implements(ZoneGetter.class)
+public class ShadowZoneGetter {
+
+ @Implementation
+ public static List<Map<String, Object>> getZonesList(Context context) {
+ List<Map<String, Object>> zones = new ArrayList<>();
+ zones.add(createDisplayEntry(TimeZone.getDefault(), "gmt-1:00", "FakePlace", 10000));
+ return zones;
+ }
+
+ private static Map<String, Object> createDisplayEntry(
+ TimeZone tz, CharSequence gmtOffsetText, CharSequence displayName, int offsetMillis) {
+ Map<String, Object> map = new HashMap<>();
+ map.put(ZoneGetter.KEY_ID, tz.getID());
+ map.put(ZoneGetter.KEY_DISPLAYNAME, displayName.toString());
+ map.put(ZoneGetter.KEY_DISPLAY_LABEL, displayName);
+ map.put(ZoneGetter.KEY_GMT, gmtOffsetText.toString());
+ map.put(ZoneGetter.KEY_OFFSET_LABEL, gmtOffsetText);
+ map.put(ZoneGetter.KEY_OFFSET, offsetMillis);
+ return map;
+ }
+}
diff --git a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
index 231787e..3137d59 100644
--- a/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/display/ThemePreferenceControllerTest.java
@@ -14,95 +14,115 @@
* limitations under the License.
*/
-package com.android.settings.core;
-
-import static junit.framework.TestCase.assertNotNull;
+package com.android.settings.display;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.UiModeManager;
-import android.content.Context;
import android.content.ContextWrapper;
+import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.v7.preference.ListPreference;
-import com.android.settings.R;
import com.android.settings.display.ThemePreferenceController;
+import com.android.settings.display.ThemePreferenceController.OverlayManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import java.util.ArrayList;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ThemePreferenceControllerTest {
- private UiModeManager mMockUiModeManager;
+ private OverlayManager mMockOverlayManager;
private ContextWrapper mContext;
private ThemePreferenceController mPreferenceController;
+ private PackageManager mMockPackageManager;
@Before
public void setup() {
- mMockUiModeManager = mock(UiModeManager.class);
- mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
+ mMockOverlayManager = mock(OverlayManager.class);
+ mMockPackageManager = mock(PackageManager.class);
+ mContext = new ContextWrapper(InstrumentationRegistry.getContext()) {
@Override
- public Object getSystemService(String name) {
- if (Context.UI_MODE_SERVICE.equals(name)) {
- return mMockUiModeManager;
- }
- return super.getSystemService(name);
+ public PackageManager getPackageManager() {
+ return mMockPackageManager;
}
};
- mPreferenceController = new ThemePreferenceController(mContext);
+ mPreferenceController = new ThemePreferenceController(mContext, mMockOverlayManager);
}
@Test
- public void testUpdateState() {
- when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[] {
- null,
- "Theme1",
- "Theme2",
+ public void testUpdateState() throws Exception {
+ OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android",
+ "", OverlayInfo.STATE_ENABLED, 0);
+ OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android",
+ "", 0, 0);
+ when(mMockPackageManager.getApplicationInfo(any(), anyInt())).thenAnswer(inv -> {
+ ApplicationInfo info = mock(ApplicationInfo.class);
+ if ("com.android.Theme1".equals(inv.getArguments()[0])) {
+ when(info.loadLabel(any())).thenReturn("Theme1");
+ } else {
+ when(info.loadLabel(any())).thenReturn("Theme2");
+ }
+ return info;
});
- when(mMockUiModeManager.getTheme()).thenReturn("Theme1");
+ when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
+ list(info1, info2));
ListPreference pref = mock(ListPreference.class);
mPreferenceController.updateState(pref);
ArgumentCaptor<String[]> arg = ArgumentCaptor.forClass(String[].class);
verify(pref).setEntries(arg.capture());
- String[] entries = arg.getValue();
- assertEquals(3, entries.length);
- assertNotNull(entries[0]);
- assertEquals("Theme1", entries[1]);
- assertEquals("Theme2", entries[2]);
+
+ CharSequence[] entries = arg.getValue();
+ assertEquals(2, entries.length);
+ assertEquals("Theme1", entries[0]);
+ assertEquals("Theme2", entries[1]);
verify(pref).setEntryValues(arg.capture());
- String[] entryValues = arg.getValue();
- assertEquals(3, entryValues.length);
- assertNotNull(entryValues[0]);
- assertEquals("Theme1", entryValues[1]);
- assertEquals("Theme2", entryValues[2]);
+ CharSequence[] entryValues = arg.getValue();
+ assertEquals("com.android.Theme1", entryValues[0]);
+ assertEquals("com.android.Theme2", entryValues[1]);
- verify(pref).setValue(eq("Theme1"));
+ verify(pref).setValue(eq("com.android.Theme1"));
}
@Test
- public void testAvailable_false() {
- when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[1]);
+ public void testAvailable_false() throws Exception {
+ when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
+ .thenReturn(list(new OverlayInfo("", "", "", 0, 0)));
assertFalse(mPreferenceController.isAvailable());
}
@Test
- public void testAvailable_true() {
- when(mMockUiModeManager.getAvailableThemes()).thenReturn(new String[2]);
+ public void testAvailable_true() throws Exception {
+ when(mMockOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
+ .thenReturn(list(new OverlayInfo("", "", "", 0, 0),
+ new OverlayInfo("", "", "", 0, 0)));
assertTrue(mPreferenceController.isAvailable());
}
+
+ private ArrayList<OverlayInfo> list(OverlayInfo... infos) {
+ ArrayList<OverlayInfo> list = new ArrayList<>();
+ for (int i = 0; i < infos.length; i++) {
+ list.add(infos[i]);
+ }
+ return list;
+ }
}