Merge "Suppress some search results" into oc-mr1-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d553573..9c71c4f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -798,7 +798,7 @@
<activity android:name=".support.NewDeviceIntroSuggestionActivity"
android:label="@string/new_device_suggestion_title"
- android:icon="@drawable/ic_new_releases_24dp"
+ android:icon="@drawable/ic_new_device_suggestion_24dp"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/res/drawable-nodpi/fingerprint_enroll_introduction.png b/res/drawable-nodpi/fingerprint_enroll_introduction.png
new file mode 100644
index 0000000..268ca43
--- /dev/null
+++ b/res/drawable-nodpi/fingerprint_enroll_introduction.png
Binary files differ
diff --git a/res/drawable/ic_new_releases_24dp.xml b/res/drawable/ic_new_device_suggestion_24dp.xml
similarity index 100%
rename from res/drawable/ic_new_releases_24dp.xml
rename to res/drawable/ic_new_device_suggestion_24dp.xml
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index 7ce3034..f1b631e 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -21,7 +21,7 @@
android:layout_height="match_parent"
android:icon="@drawable/ic_lock"
settings:suwFooter="@layout/choose_lock_password_footer"
- settings:suwHeaderText="@string/lockpassword_choose_your_password_header">
+ settings:suwHeaderText="@string/lockpassword_choose_your_screen_lock_header">
<LinearLayout
style="@style/SuwContentFrame"
@@ -33,11 +33,11 @@
android:orientation="vertical">
<TextView
- android:id="@+id/fingerprint_backup_message"
+ android:id="@+id/message"
style="@style/SuwDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:visibility="gone" />
+ android:minLines="2"/>
<LinearLayout
android:id="@+id/password_container"
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index 4f73395..4228f42 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -45,6 +45,20 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
+ <com.android.setupwizardlib.view.FillContentLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <ImageView
+ style="@style/SuwContentIllustration"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@null"
+ android:src="@drawable/fingerprint_enroll_introduction" />
+
+ </com.android.setupwizardlib.view.FillContentLayout>
+
</LinearLayout>
</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/setup_choose_lock_generic_fingerprint_header.xml b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
index 4c696f3..ec5d750 100644
--- a/res/layout/setup_choose_lock_generic_fingerprint_header.xml
+++ b/res/layout/setup_choose_lock_generic_fingerprint_header.xml
@@ -23,4 +23,4 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="@dimen/suw_description_glif_margin_top"
android:paddingBottom="@dimen/suw_description_glif_margin_bottom_lists"
- android:text="@string/setup_lock_settings_picker_fingerprint_message" />
+ android:text="@string/lock_settings_picker_fingerprint_added_security_message" />
diff --git a/res/values-mcc262-mnc02/strings.xml b/res/values-mcc262-mnc02/strings.xml
index 17f9272..280f59e 100644
--- a/res/values-mcc262-mnc02/strings.xml
+++ b/res/values-mcc262-mnc02/strings.xml
@@ -16,4 +16,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Wi-Fi Calling settings. Additional text displayed when Wi-Fi Calling is off. Default empty. [CHAR LIMIT=NONE] -->
<string name="wifi_calling_off_explanation_2">\n\nYou can\u2019t make emergency calls through Wi-Fi calling. If you try to make an emergency call, your device will automatically use the mobile network. Emergency calls can only be made in areas with mobile network coverage.</string>
+ <!-- Do not translate. Wireless networks, item title to go into the WFC settings [CHAR LIMIT=30] -->
+ <string name="wifi_calling_settings_title">"Wi-Fi calling"</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 14884a2..6366b9e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -835,9 +835,9 @@
<!-- Button text to continue to the next screen from the introduction (this string variant is used while in setup wizard) [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_enroll_introduction_continue_setup">Next</string>
<!-- Title of dialog shown when the user tries to skip setting up fingerprint after adding lock screen during initial setup. [CHAR LIMIT=30] -->
- <string name="fingerprint_enroll_skip_after_adding_lock_title">Skip fingerprint setup?</string>
+ <string name="setup_fingerprint_enroll_skip_title">Skip fingerprint?</string>
<!-- Body text of dialog shown when the user tries to skip setting up fingerprint after adding lock screen during initial setup [CHAR LIMIT=NONE] -->
- <string name="fingerprint_enroll_skip_after_adding_lock_text">You\u2019ve chosen to use your fingerprint as one way to unlock your phone. If you skip now, you\u2019ll need to set this up later. Setup takes only a minute or so.</string>
+ <string name="setup_fingerprint_enroll_skip_after_adding_lock_text">Fingerprint setup only takes a minute or two. If you skip this, you can add your fingerprint later in settings.</string>
<!-- Title of dialog shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so [CHAR LIMIT=30]-->
<string name="lock_screen_intro_skip_title">Skip screen lock?</string>
<!-- Dialog text shown when the user tries to skip setting up a screen lock, warning them of potential consequences of not doing so, including loss of factory reset protection. (tablet) [CHAR LIMIT=NONE] -->
@@ -1105,8 +1105,8 @@
<!-- Title for security picker in setup wizard to choose the unlock method: None/Pattern/PIN/Password (phone) [CHAR LIMIT=22] -->
<string name="setup_lock_settings_picker_title" product="default">Protect your phone</string>
- <!-- Title for screen in setup wizard, prompting user to choose the their backup screen lock method [CHAR LIMIT=NONE] -->
- <string name="setup_lock_settings_picker_fingerprint_message">For added security, set up a backup screen lock.</string>
+ <!-- Message shown when setting up screen lock, prompting user to choose the their backup screen lock method [CHAR LIMIT=NONE] -->
+ <string name="lock_settings_picker_fingerprint_added_security_message">For added security, set up a backup screen lock.</string>
<!-- Description text for screen in setup wizard asking user to set up screen lock, explaining to the user how setting up a screen lock protect them from losing data. (tablet) [CHAR LIMIT=NONE] -->
<string name="setup_lock_settings_picker_message" product="tablet">Prevent others from using this tablet without your permission by activating device protection features. Choose the screen lock you want to use.</string>
@@ -1381,7 +1381,7 @@
<!-- Label for ChoosePassword/PIN OK button -->
<string name="lockpassword_cancel_label">Cancel</string>
- <!-- Label for ChoosePassword/PIN OK button -->
+ <!-- Label for ChoosePassword/PIN Clear button that clears all text entered by the user so far. -->
<string name="lockpassword_clear_label">Clear</string>
<!-- Label for LockPatternTutorial Cancel button -->
@@ -3427,24 +3427,26 @@
<string name="settings_safetylegal_activity_loading">Loading\u2026</string>
<!-- Lock Pattern settings -->
- <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=30] -->
- <string name="lockpassword_choose_your_password_header">Choose your password</string>
+ <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=40] -->
+ <string name="lockpassword_choose_your_screen_lock_header">Set a screen lock</string>
+ <!-- Message on first screen of choose password flow [CHAR LIMIT=NONE] -->
+ <string name="lockpassword_choose_your_password_message">For security, set a password</string>
<!-- Header on first screen of choose password/PIN as backup for fingerprint flow [CHAR LIMIT=30] -->
<string name="lockpassword_choose_your_password_header_for_fingerprint">To use fingerprint, set password</string>
<!-- Header on first screen of choose pattern flow [CHAR LIMIT=30] -->
<string name="lockpassword_choose_your_pattern_header">Choose your pattern</string>
<!-- Header on first screen of choose pattern as backup for fingerprint flow [CHAR LIMIT=30] -->
<string name="lockpassword_choose_your_pattern_header_for_fingerprint">To use fingerprint, set pattern</string>
- <!-- Header on first screen of choose password/PIN flow [CHAR LIMIT=30] -->
- <string name="lockpassword_choose_your_pin_header">Choose your PIN</string>
+ <!-- Message on first screen of choose PIN flow [CHAR LIMIT=NONE] -->
+ <string name="lockpassword_choose_your_pin_message">For security, set a PIN</string>
<!-- Header on first screen of choose password/PIN as backup for fingerprint flow [CHAR LIMIT=30] -->
<string name="lockpassword_choose_your_pin_header_for_fingerprint">To use fingerprint, set PIN</string>
- <!-- Header on password confirm screen [CHAR LIMIT=30] -->
- <string name="lockpassword_confirm_your_password_header">Confirm your password</string>
+ <!-- Header on password confirm screen [CHAR LIMIT=40] -->
+ <string name="lockpassword_confirm_your_password_header">Re-enter your password</string>
<!-- Header on pattern confirm screen [CHAR LIMIT=30] -->
<string name="lockpassword_confirm_your_pattern_header">Confirm your pattern</string>
- <!-- Header on password confirm screen [CHAR LIMIT=30] -->
- <string name="lockpassword_confirm_your_pin_header">Confirm your PIN</string>
+ <!-- Header on password confirm screen [CHAR LIMIT=40] -->
+ <string name="lockpassword_confirm_your_pin_header">Re-enter your PIN</string>
<!-- Header on password confirm screen if second password doesn't match the first. [CHAR LIMIT=30] -->
<string name="lockpassword_confirm_passwords_dont_match">Passwords don\u2019t match</string>
<!-- Header on pin confirm screen if second pin doesn't match the first. [CHAR LIMIT=30]-->
@@ -8780,8 +8782,8 @@
<!-- Section title for the Web Action preference [CHAR LIMIT=60] -->
<string name="web_action_section_title">Instant apps</string>
- <!-- Preference label for an tappable preference that will open the account chooser for instant apps. [CHAR LIMIT=60] -->
- <string name="instant_apps_account">Instant apps account</string>
+ <!-- Preference label for an tappable preference that will open the instant apps settings. [CHAR LIMIT=60] -->
+ <string name="instant_apps_settings">Instant Apps preferences</string>
<!-- Section title for the Domain URL app preference list [CHAR LIMIT=60]-->
<string name="domain_url_section_title">Installed apps</string>
@@ -9029,7 +9031,13 @@
<string name="new_device_suggestion_title">What\'s new and exciting?</string>
<!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
- <string name="new_device_suggestion_summary">Check out the top 5 features</string>
+ <string name="new_device_suggestion_summary" product="default">Take a tour of your new phone</string>
+
+ <!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+ <string name="new_device_suggestion_summary" product="tablet">Take a tour of your new tablet</string>
+
+ <!-- Summary label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
+ <string name="new_device_suggestion_summary" product="device">Take a tour of your new device</string>
<!-- The divider symbol between different parts of the notification header including spaces. not translatable [CHAR LIMIT=3] -->
<string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 1a8f3de..2610e08 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -25,7 +25,6 @@
<style name="GlifTheme" parent="SuwThemeGlif">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
- <item name="android:colorPrimary">@color/suw_color_accent_dark</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -46,7 +45,6 @@
<style name="GlifTheme.Light" parent="SuwThemeGlif.Light">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
- <item name="android:colorPrimary">@color/suw_color_accent_light</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -66,7 +64,6 @@
<style name="GlifV2Theme" parent="SuwThemeGlifV2">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
- <item name="android:colorPrimary">@color/suw_color_accent_dark</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
@@ -87,7 +84,6 @@
<style name="GlifV2Theme.Light" parent="SuwThemeGlifV2.Light">
<!-- For all Alert Dialogs -->
<item name="android:alertDialogTheme">@style/ThemeOverlay.AlertDialog</item>
- <item name="android:colorPrimary">@color/suw_color_accent_light</item>
<item name="android:windowBackground">?android:attr/colorBackground</item>
<item name="*android:preferencePanelStyle">@*android:style/PreferencePanel.Dialog</item>
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
diff --git a/res/xml/available_virtual_keyboard.xml b/res/xml/available_virtual_keyboard.xml
new file mode 100644
index 0000000..9a0b3c6
--- /dev/null
+++ b/res/xml/available_virtual_keyboard.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:key="available_virtual_keyboard_page"
+ android:title="@string/add_virtual_keyboard">
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/security_settings_password_sub.xml b/res/xml/security_settings_password_sub.xml
index 46c4999..c0287c0 100644
--- a/res/xml/security_settings_password_sub.xml
+++ b/res/xml/security_settings_password_sub.xml
@@ -22,7 +22,7 @@
<com.android.settings.TimeoutListPreference
android:key="lock_after_timeout"
android:title="@string/lock_after_timeout"
- android:summary="@string/lock_after_timeout_summary"
+ android:summary="@string/summary_placeholder"
android:entries="@array/lock_after_timeout_entries"
android:entryValues="@array/lock_after_timeout_values" />
@@ -32,7 +32,6 @@
<com.android.settingslib.RestrictedPreference
android:key="owner_info_settings"
- android:title="@string/owner_info_settings_title"
- android:summary="@string/owner_info_settings_summary" />
+ android:title="@string/owner_info_settings_title" />
</PreferenceScreen>
diff --git a/res/xml/security_settings_pin_sub.xml b/res/xml/security_settings_pin_sub.xml
index 46c4999..c0287c0 100644
--- a/res/xml/security_settings_pin_sub.xml
+++ b/res/xml/security_settings_pin_sub.xml
@@ -22,7 +22,7 @@
<com.android.settings.TimeoutListPreference
android:key="lock_after_timeout"
android:title="@string/lock_after_timeout"
- android:summary="@string/lock_after_timeout_summary"
+ android:summary="@string/summary_placeholder"
android:entries="@array/lock_after_timeout_entries"
android:entryValues="@array/lock_after_timeout_values" />
@@ -32,7 +32,6 @@
<com.android.settingslib.RestrictedPreference
android:key="owner_info_settings"
- android:title="@string/owner_info_settings_title"
- android:summary="@string/owner_info_settings_summary" />
+ android:title="@string/owner_info_settings_title" />
</PreferenceScreen>
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index f120b7f..609120d 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -59,7 +59,6 @@
import com.android.settings.dashboard.DashboardSummary;
import com.android.settings.development.DevelopmentSettings;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.search.DynamicIndexableContentMonitor;
import com.android.settings.search.SearchActivity;
import com.android.settings.wfd.WifiDisplaySettings;
import com.android.settings.widget.SwitchBar;
@@ -76,8 +75,6 @@
private static final String LOG_TAG = "Settings";
- public static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
-
// Constants for state save/restore
private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
@VisibleForTesting
@@ -183,8 +180,6 @@
}
};
- private DynamicIndexableContentMonitor mDynamicIndexableContentMonitor;
-
private SwitchBar mSwitchBar;
private Button mNextButton;
@@ -535,10 +530,6 @@
mDevelopmentPreferencesListener);
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- if (mDynamicIndexableContentMonitor == null) {
- mDynamicIndexableContentMonitor = new DynamicIndexableContentMonitor();
- }
- mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
updateTilesList();
}
@@ -550,9 +541,6 @@
mDevelopmentPreferencesListener);
mDevelopmentPreferencesListener = null;
unregisterReceiver(mBatteryInfoReceiver);
- if (mDynamicIndexableContentMonitor != null) {
- mDynamicIndexableContentMonitor.unregister(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
- }
}
@Override
diff --git a/src/com/android/settings/applications/ManageDomainUrls.java b/src/com/android/settings/applications/ManageDomainUrls.java
index 2149fbd..1d325ce 100644
--- a/src/com/android/settings/applications/ManageDomainUrls.java
+++ b/src/com/android/settings/applications/ManageDomainUrls.java
@@ -141,7 +141,7 @@
final Intent launchIntent = instantAppSettingsIntent;
// TODO: Make this button actually launch the account chooser.
mInstantAppAccountPreference = new Preference(getPrefContext());
- mInstantAppAccountPreference.setTitle(R.string.instant_apps_account);
+ mInstantAppAccountPreference.setTitle(R.string.instant_apps_settings);
mInstantAppAccountPreference.setOnPreferenceClickListener(pref -> {
startActivity(launchIntent);
return true;
diff --git a/src/com/android/settings/applications/assist/ManageAssist.java b/src/com/android/settings/applications/assist/ManageAssist.java
index eb14ea1..4126aaf 100644
--- a/src/com/android/settings/applications/assist/ManageAssist.java
+++ b/src/com/android/settings/applications/assist/ManageAssist.java
@@ -22,7 +22,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.gestures.AssistGesturePreferenceController;
+import com.android.settings.gestures.AssistGestureSettingsPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -73,8 +73,8 @@
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new DefaultAssistPreferenceController(context, "default_assist",
true /* showSetting */));
- controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
- true /* assistOnly */));
+ controllers.add(new AssistGestureSettingsPreferenceController(context, lifecycle,
+ KEY_ASSIST, true /* assistOnly */));
controllers.add(new AssistContextPreferenceController(context, lifecycle));
controllers.add(new AssistScreenshotPreferenceController(context, lifecycle));
controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle));
diff --git a/src/com/android/settings/bluetooth/AlwaysDiscoverable.java b/src/com/android/settings/bluetooth/AlwaysDiscoverable.java
new file mode 100644
index 0000000..5d7cbd5
--- /dev/null
+++ b/src/com/android/settings/bluetooth/AlwaysDiscoverable.java
@@ -0,0 +1,87 @@
+/*
+ * 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.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+/** Helper class, intended to be used by an Activity, to keep the local Bluetooth adapter in
+ * discoverable mode indefinitely. By default setting the scan mode to
+ * BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE will time out after some time, but some
+ * Bluetooth settings pages would like to keep the device discoverable as long as the page is
+ * visible. */
+public class AlwaysDiscoverable extends BroadcastReceiver {
+ private static final String TAG = "AlwaysDiscoverable";
+
+ private Context mContext;
+ private LocalBluetoothAdapter mLocalAdapter;
+ private IntentFilter mIntentFilter;
+
+ @VisibleForTesting
+ boolean mStarted;
+
+ public AlwaysDiscoverable(Context context, LocalBluetoothAdapter localAdapter) {
+ mContext = context;
+ mLocalAdapter = localAdapter;
+ mIntentFilter = new IntentFilter();
+ mIntentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
+ }
+
+ /** After calling start(), consumers should make a matching call to stop() when they no longer
+ * wish to enforce discoverable mode. */
+ public void start() {
+ if (mStarted) {
+ return;
+ }
+ mContext.registerReceiver(this, mIntentFilter);
+ mStarted = true;
+ if (mLocalAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+ mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ }
+ }
+
+ public void stop() {
+ if (!mStarted) {
+ return;
+ }
+ mContext.unregisterReceiver(this);
+ mStarted = false;
+ mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action != BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) {
+ return;
+ }
+ if (mLocalAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
+ mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ }
+ }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
index 5cc1060..60011f9 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDetail.java
@@ -53,6 +53,8 @@
BluetoothProgressCategory mAvailableDevicesCategory;
@VisibleForTesting
FooterPreference mFooterPreference;
+ @VisibleForTesting
+ AlwaysDiscoverable mAlwaysDiscoverable;
private boolean mInitialScanStarted;
@@ -64,6 +66,7 @@
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mInitialScanStarted = false;
+ mAlwaysDiscoverable = new AlwaysDiscoverable(getContext(), mLocalAdapter);
}
@Override
@@ -79,7 +82,7 @@
super.onStop();
// Make the device only visible to connected devices.
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+ mAlwaysDiscoverable.stop();
disableScanning();
}
@@ -132,9 +135,7 @@
R.string.bluetooth_preference_found_devices,
BluetoothDeviceFilter.UNBONDED_DEVICE_FILTER, mInitialScanStarted);
updateFooterPreference(mFooterPreference);
- // mLocalAdapter.setScanMode is internally synchronized so it is okay for multiple
- // threads to execute.
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ mAlwaysDiscoverable.start();
enableScanning();
break;
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
index f95ce46..1aac0ff 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java
@@ -25,6 +25,7 @@
import android.text.InputFilter;
import android.text.InputFilter.LengthFilter;
import android.text.InputType;
+import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
@@ -34,6 +35,7 @@
import android.widget.EditText;
import android.widget.TextView;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -186,6 +188,19 @@
}
/**
+ * Helper method to return the text of the pin entry field - this exists primarily to help us
+ * simulate having existing text when the dialog is recreated, for example after a screen
+ * rotation.
+ */
+ @VisibleForTesting
+ CharSequence getPairingViewText() {
+ if (mPairingView != null) {
+ return mPairingView.getText();
+ }
+ return null;
+ }
+
+ /**
* Returns a dialog with UI elements that allow a user to provide input.
*/
private AlertDialog createUserEntryDialog() {
@@ -196,7 +211,9 @@
mBuilder.setNegativeButton(getString(android.R.string.cancel), this);
AlertDialog dialog = mBuilder.create();
dialog.setOnShowListener(d -> {
- mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
+ if (TextUtils.isEmpty(getPairingViewText())) {
+ mDialog.getButton(Dialog.BUTTON_POSITIVE).setEnabled(false);
+ }
if (mPairingView != null && mPairingView.requestFocus()) {
InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index adfb721..bd86c4b 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -80,6 +80,7 @@
FooterPreference mFooterPreference;
private Preference mPairingPreference;
private BluetoothEnabler mBluetoothEnabler;
+ private AlwaysDiscoverable mAlwaysDiscoverable;
private SwitchBar mSwitchBar;
@@ -111,6 +112,9 @@
mMetricsFeatureProvider, Utils.getLocalBtManager(activity),
MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
mBluetoothEnabler.setupSwitchController();
+ if (mLocalAdapter != null) {
+ mAlwaysDiscoverable = new AlwaysDiscoverable(getContext(), mLocalAdapter);
+ }
}
@Override
@@ -157,7 +161,9 @@
}
// Make the device only visible to connected devices.
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+ if (mAlwaysDiscoverable != null) {
+ mAlwaysDiscoverable.stop();
+ }
if (isUiRestricted()) {
return;
@@ -188,7 +194,9 @@
mPairedDevicesCategory.addPreference(mPairingPreference);
updateFooterPreference(mFooterPreference);
- mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ if (mAlwaysDiscoverable != null) {
+ mAlwaysDiscoverable.start();
+ }
return; // not break
case BluetoothAdapter.STATE_TURNING_OFF:
diff --git a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
index b4e6158..dee40c0 100644
--- a/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
+++ b/src/com/android/settings/core/instrumentation/SharedPreferencesLogger.java
@@ -120,19 +120,29 @@
final Pair<Integer, Object> valueData;
if (value instanceof Long) {
- valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
- value);
+ final Long longVal = (Long) value;
+ final int intVal;
+ if (longVal > Integer.MAX_VALUE) {
+ intVal = Integer.MAX_VALUE;
+ } else if (longVal < Integer.MIN_VALUE) {
+ intVal = Integer.MIN_VALUE;
+ } else {
+ intVal = longVal.intValue();
+ }
+ valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+ intVal);
} else if (value instanceof Integer) {
- valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
- ((Integer) value).longValue());
+ valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+ value);
} else if (value instanceof Boolean) {
- valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE,
- (Boolean) value ? 1L : 0L);
+ valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+ (Boolean) value ? 1 : 0);
} else if (value instanceof Float) {
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
value);
} else if (value instanceof String) {
- valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_VALUE, value);
+ Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
+ valueData = null;
} else {
Log.w(LOG_TAG, "Tried to log unloggable object" + value);
valueData = null;
diff --git a/src/com/android/settings/fingerprint/FingerprintSettings.java b/src/com/android/settings/fingerprint/FingerprintSettings.java
index 4eddcb1..7ebf294 100644
--- a/src/com/android/settings/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/fingerprint/FingerprintSettings.java
@@ -129,7 +129,6 @@
public static class FingerprintSettingsFragment extends SettingsPreferenceFragment
implements OnPreferenceChangeListener, FingerprintPreference.OnDeleteClickListener {
- private static final int MAX_RETRY_ATTEMPTS = 20;
private static final int RESET_HIGHLIGHT_DELAY_MS = 500;
private static final String TAG = "FingerprintSettings";
@@ -284,6 +283,11 @@
if (mRemovalSidecar.inProgress()) {
return;
}
+ // Don't start authentication if ChooseLockGeneric is showing, otherwise if the user
+ // is in FP lockout, a toast will show on top
+ if (mLaunchedConfirm) {
+ return;
+ }
if (!mInFingerprintLockout) {
mFingerprintCancel = new CancellationSignal();
mFingerprintManager.authenticate(null, mFingerprintCancel, 0 /* flags */,
@@ -432,6 +436,7 @@
@Override
public void onResume() {
super.onResume();
+ mInFingerprintLockout = false;
// Make sure we reload the preference hierarchy since fingerprints may be added,
// deleted or renamed.
updatePreferences();
@@ -545,6 +550,7 @@
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CHOOSE_LOCK_GENERIC_REQUEST
|| requestCode == CONFIRM_REQUEST) {
+ mLaunchedConfirm = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
// The lock pin/pattern/password was set. Start enrolling!
if (data != null) {
diff --git a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
index 85e3417..2137130 100644
--- a/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -78,10 +78,10 @@
@NonNull
public AlertDialog.Builder onCreateDialogBuilder() {
return new AlertDialog.Builder(getContext())
- .setTitle(R.string.fingerprint_enroll_skip_after_adding_lock_title)
+ .setTitle(R.string.setup_fingerprint_enroll_skip_title)
.setPositiveButton(R.string.skip_anyway_button_label, this)
.setNegativeButton(R.string.go_back_button_label, this)
- .setMessage(R.string.fingerprint_enroll_skip_after_adding_lock_text);
+ .setMessage(R.string.setup_fingerprint_enroll_skip_after_adding_lock_text);
}
@Override
diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java
index 3066baf..8878f47 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -35,8 +35,6 @@
private static final String TAG = "AssistGesture";
- private static final String KEY_ASSIST = "gesture_assist";
-
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_ASSIST_GESTURE;
@@ -60,8 +58,6 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
- false /* assistOnly */));
controllers.addAll(FeatureFactory.getFactory(context).getAssistGestureFeatureProvider()
.getControllers(context, lifecycle));
@@ -86,8 +82,8 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
- return new AssistGesturePreferenceController(context, null /* lifecycle */,
- null /* key */, false /* assistOnly */)
+ return new AssistGestureSettingsPreferenceController(context,
+ null /* lifecycle */, null /* key */, false /* assistOnly */)
.isAvailable();
}
};
diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
similarity index 72%
rename from src/com/android/settings/gestures/AssistGesturePreferenceController.java
rename to src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
index b91f230..bf6ee8c 100644
--- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/AssistGestureSettingsPreferenceController.java
@@ -16,6 +16,9 @@
package com.android.settings.gestures;
+import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
+import static android.provider.Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED;
+
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
@@ -32,19 +35,17 @@
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.events.OnResume;
-import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
-
-public class AssistGesturePreferenceController extends GesturePreferenceController
+public class AssistGestureSettingsPreferenceController extends GesturePreferenceController
implements OnResume {
- private final int ON = 1;
- private final int OFF = 0;
-
private static final String PREF_KEY_VIDEO = "gesture_assist_video";
+
+ private static final String SECURE_KEY_ASSIST = ASSIST_GESTURE_ENABLED;
+ private static final String SECURE_KEY_SILENCE = ASSIST_GESTURE_SILENCE_ALERTS_ENABLED;
+ private static final int ON = 1;
+ private static final int OFF = 0;
+
private final String mAssistGesturePrefKey;
-
- private final String SECURE_KEY = ASSIST_GESTURE_ENABLED;
-
private final AssistGestureFeatureProvider mFeatureProvider;
private boolean mWasAvailable;
@@ -54,8 +55,8 @@
@VisibleForTesting
boolean mAssistOnly;
- public AssistGesturePreferenceController(Context context, Lifecycle lifecycle, String key,
- boolean assistOnly) {
+ public AssistGestureSettingsPreferenceController(Context context, Lifecycle lifecycle,
+ String key, boolean assistOnly) {
super(context, lifecycle);
mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider();
mWasAvailable = isAvailable();
@@ -76,14 +77,6 @@
public void displayPreference(PreferenceScreen screen) {
mScreen = screen;
mPreference = screen.findPreference(getPreferenceKey());
- if (!mFeatureProvider.isSensorAvailable(mContext)) {
- removePreference(mScreen, getPreferenceKey());
- return;
- }
- if (!mFeatureProvider.isSupported(mContext)) {
- mScreen.removePreference(mPreference);
- return;
- }
// Call super last or AbstractPreferenceController might remove the preference from the
// screen (if !isAvailable()) before we can save a reference to it.
super.displayPreference(screen);
@@ -91,14 +84,6 @@
@Override
public void onResume() {
- // This check must be done in case the user disables Assistant while still on the settings
- // page. This check is slightly different than isAvailable() in some cases due to this
- // setting being in multiple places that require different behavior
- if (mScreen != null && !mFeatureProvider.isSupported(mContext)) {
- mScreen.removePreference(mPreference);
- mWasAvailable = false;
- return;
- }
if (mWasAvailable != isAvailable()) {
// Only update the preference visibility if the availability has changed -- otherwise
// the preference may be incorrectly added to screens with collapsed sections.
@@ -112,7 +97,7 @@
return;
}
- if (mFeatureProvider.isSupported(mContext)) {
+ if (isAvailable()) {
if (mScreen.findPreference(getPreferenceKey()) == null) {
mScreen.addPreference(mPreference);
}
@@ -121,15 +106,22 @@
}
}
+ private boolean isAssistGestureEnabled() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ SECURE_KEY_ASSIST, ON) != 0;
+ }
+
+ private boolean isSilenceGestureEnabled() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ SECURE_KEY_SILENCE, ON) != 0;
+ }
+
@Override
public void updateState(Preference preference) {
- boolean isEnabled = isSwitchPrefEnabled() && mFeatureProvider.isSupported(mContext);
+ boolean isEnabled = isAssistGestureEnabled() && mFeatureProvider.isSupported(mContext);
if (!mAssistOnly) {
- boolean assistGestureSilenceEnabled = Settings.Secure.getInt(
- mContext.getContentResolver(),
- Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, 1) != 0;
- isEnabled = isEnabled || assistGestureSilenceEnabled;
+ isEnabled = isEnabled || isSilenceGestureEnabled();
}
if (preference != null) {
@@ -146,7 +138,8 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean enabled = (boolean) newValue;
- Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, enabled ? ON : OFF);
+ Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY_ASSIST,
+ enabled ? ON : OFF);
updateState(preference);
return true;
}
@@ -163,9 +156,8 @@
@Override
protected boolean isSwitchPrefEnabled() {
- final int assistGestureEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
- SECURE_KEY, ON);
- return assistGestureEnabled != 0;
+ // Does nothing
+ return true;
}
@Override
@@ -174,7 +166,7 @@
AssistGestureSettings.class.getName(), mAssistGesturePrefKey,
mContext.getString(R.string.display_settings));
- return new InlineSwitchPayload(SECURE_KEY, ResultPayload.SettingsSource.SECURE,
+ return new InlineSwitchPayload(SECURE_KEY_ASSIST, ResultPayload.SettingsSource.SECURE,
ON /* onValue */, intent, isAvailable(), ON /* defaultValue */);
}
}
diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java
index 805c4a1..4d38b09 100644
--- a/src/com/android/settings/gestures/GestureSettings.java
+++ b/src/com/android/settings/gestures/GestureSettings.java
@@ -75,8 +75,8 @@
@NonNull Context context, @Nullable Lifecycle lifecycle,
@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new AssistGesturePreferenceController(context, lifecycle, KEY_ASSIST,
- false /* assistOnly */));
+ controllers.add(new AssistGestureSettingsPreferenceController(context, lifecycle,
+ KEY_ASSIST, false /* assistOnly */));
controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
KEY_SWIPE_DOWN));
controllers.add(new DoubleTwistPreferenceController(context, lifecycle, KEY_DOUBLE_TWIST));
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index 3b5dbba..6f334a5 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -17,29 +17,24 @@
package com.android.settings.gestures;
import android.content.Context;
-import android.content.Intent;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.support.v7.preference.Preference;
-import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.search.DatabaseIndexingUtils;
-import com.android.settings.search.InlineSwitchPayload;
-import com.android.settings.search.ResultPayload;
import com.android.settingslib.core.lifecycle.Lifecycle;
import static android.provider.Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED;
public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
- private final int ON = 1;
- private final int OFF = 0;
+ private static final int ON = 1;
+ private static final int OFF = 0;
private static final String PREF_KEY_VIDEO = "gesture_swipe_down_fingerprint_video";
private final String mSwipeDownFingerPrefKey;
- private final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
+ private static final String SECURE_KEY = SYSTEM_NAVIGATION_KEYS_ENABLED;
public SwipeToNotificationPreferenceController(Context context, Lifecycle lifecycle,
String key) {
@@ -70,28 +65,30 @@
@Override
public boolean isAvailable() {
- return isGestureAvailable(mContext);
+ return SwipeToNotificationPreferenceController.isAvailable(mContext);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY,
- (boolean) newValue ? ON : OFF);
+ setSwipeToNotification(mContext, (boolean) newValue);
return true;
}
@Override
protected boolean isSwitchPrefEnabled() {
- return Settings.Secure.getInt(mContext.getContentResolver(), SECURE_KEY, OFF) == ON;
+ return isSwipeToNotificationOn(mContext);
}
- @Override
- public ResultPayload getResultPayload() {
- final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(mContext,
- SwipeToNotificationSettings.class.getName(), mSwipeDownFingerPrefKey,
- mContext.getString(R.string.display_settings));
+ public static boolean isSwipeToNotificationOn(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(), SECURE_KEY, OFF) == ON;
+ }
- return new InlineSwitchPayload(SECURE_KEY, ResultPayload.SettingsSource.SECURE,
- ON /* onValue */, intent, isAvailable(), OFF /* defaultValue */);
+ public static boolean setSwipeToNotification(Context context, boolean isEnabled) {
+ return Settings.Secure.putInt(
+ context.getContentResolver(), SECURE_KEY, isEnabled ? ON : OFF);
+ }
+
+ public static boolean isAvailable(Context context) {
+ return isGestureAvailable(context);
}
}
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index a7862ae..48b0b4a 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -21,7 +21,6 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -31,17 +30,15 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.support.v7.preference.PreferenceScreen;
+import android.provider.SearchIndexableResource;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import com.android.settingslib.inputmethod.InputMethodPreference;
import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
@@ -60,10 +57,9 @@
@Override
public void onCreatePreferences(Bundle bundle, String s) {
+ addPreferencesFromResource(R.xml.available_virtual_keyboard);
Activity activity = getActivity();
- PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity);
- screen.setTitle(activity.getString(R.string.available_virtual_keyboard_category));
- setPreferenceScreen(screen);
+
mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(activity);
mImm = activity.getSystemService(InputMethodManager.class);
mDpm = activity.getSystemService(DevicePolicyManager.class);
@@ -105,7 +101,7 @@
}
try {
return packageManager.getDrawable(packageName, resId, applicationInfo);
- } catch (Exception e){
+ } catch (Exception e) {
return null;
}
}
@@ -172,48 +168,16 @@
}
}
- private static List<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
- final int subtypeCount = imi.getSubtypeCount();
- final List<InputMethodSubtype> allSubtypes = new ArrayList<>(subtypeCount);
- for (int index = 0; index < subtypeCount; index++) {
- allSubtypes.add(imi.getSubtypeAt(index));
- }
- return allSubtypes;
- }
-
- static List<SearchIndexableRaw> buildSearchIndexOfInputMethods(final Context context,
- final List<InputMethodInfo> inputMethods, final String screenTitle) {
- final List<SearchIndexableRaw> indexes = new ArrayList<>();
- for (int i = 0; i < inputMethods.size(); i++) {
- final InputMethodInfo imi = inputMethods.get(i);
- final ServiceInfo serviceInfo = imi.getServiceInfo();
- final SearchIndexableRaw index = new SearchIndexableRaw(context);
- index.key = new ComponentName(serviceInfo.packageName, serviceInfo.name)
- .flattenToString();
- index.title = imi.loadLabel(context.getPackageManager()).toString();
- index.summaryOn = index.summaryOff = InputMethodAndSubtypeUtil
- .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(imi), context, imi);
- index.screenTitle = screenTitle;
- indexes.add(index);
- }
- return indexes;
- }
-
- public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
- final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
- final List<InputMethodInfo> disabledInputMethods = new ArrayList<>();
- for (final InputMethodInfo imi : imm.getInputMethodList()) {
- if (!enabledInputMethods.contains(imi)) {
- disabledInputMethods.add(imi);
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ List<SearchIndexableResource> res = new ArrayList<>();
+ SearchIndexableResource index = new SearchIndexableResource(context);
+ index.xmlResId = R.xml.available_virtual_keyboard;
+ res.add(index);
+ return res;
}
- }
- final String screenTitle = context.getString(
- R.string.available_virtual_keyboard_category);
- return buildSearchIndexOfInputMethods(context, disabledInputMethods, screenTitle);
- }
- };
+ };
}
diff --git a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
index 42eff15..83d501d 100644
--- a/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/PhysicalKeyboardFragment.java
@@ -31,6 +31,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
+import android.provider.SearchIndexableResource;
import android.provider.Settings.Secure;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
@@ -51,11 +52,11 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import java.text.Collator;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -288,6 +289,7 @@
final PhysicalKeyboardFragment mPhysicalKeyboardFragment;
@NonNull
final List<HardKeyboardDeviceInfo> mHardKeyboards;
+
public Callbacks(
@NonNull Context context,
@NonNull PhysicalKeyboardFragment physicalKeyboardFragment,
@@ -532,43 +534,14 @@
}
}
- public static List<InputDevice> getPhysicalFullKeyboards() {
- List<InputDevice> keyboards = null;
- for (final int deviceId : InputDevice.getDeviceIds()) {
- final InputDevice device = InputDevice.getDevice(deviceId);
- if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
- if (keyboards == null) keyboards = new ArrayList<>();
- keyboards.add(device);
- }
- }
- return (keyboards == null) ? Collections.emptyList() : keyboards;
- }
-
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputManager inputManager = (InputManager) context.getSystemService(
- Context.INPUT_SERVICE);
- final String screenTitle = context.getString(R.string.physical_keyboard_title);
- final List<SearchIndexableRaw> indexes = new ArrayList<>();
- for (final InputDevice device : getPhysicalFullKeyboards()) {
- final String keyboardLayoutDescriptor = inputManager
- .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
- final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
- ? inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
- final String summary = (keyboardLayout != null)
- ? keyboardLayout.toString()
- : context.getString(R.string.keyboard_layout_default_label);
- final SearchIndexableRaw index = new SearchIndexableRaw(context);
- index.key = device.getName();
- index.title = device.getName();
- index.summaryOn = summary;
- index.summaryOff = summary;
- index.screenTitle = screenTitle;
- indexes.add(index);
- }
- return indexes;
- }
- };
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.physical_keyboard_settings;
+ return Arrays.asList(sir);
+ }
+ };
}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index 7b7c599..fbe9690 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -23,6 +23,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.provider.SearchIndexableResource;
import android.support.v7.preference.Preference;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
@@ -33,14 +34,12 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
-import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
import com.android.settingslib.inputmethod.InputMethodPreference;
import java.text.Collator;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Arrays;
import java.util.List;
public final class VirtualKeyboardFragment extends SettingsPreferenceFragment implements Indexable {
@@ -121,13 +120,19 @@
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final InputMethodManager imm = context.getSystemService(InputMethodManager.class);
- final List<InputMethodInfo> enabledInputMethods = imm.getEnabledInputMethodList();
- final String screenTitle = context.getString(R.string.virtual_keyboard_category);
- return AvailableVirtualKeyboardFragment
- .buildSearchIndexOfInputMethods(context, enabledInputMethods, screenTitle);
- }
- };
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.virtual_keyboard_settings;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ final List<String> keys = super.getNonIndexableKeys(context);
+ keys.add("add_virtual_keyboard_screen");
+ return keys;
+ }
+ };
}
diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java
index fbcb02f..4affc6e 100644
--- a/src/com/android/settings/language/LanguageAndInputSettings.java
+++ b/src/com/android/settings/language/LanguageAndInputSettings.java
@@ -52,6 +52,7 @@
private static final String TAG = "LangAndInputSettings";
private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+ private static final String KEY_PHYSICAL_KEYBOARD = "physical_keyboard_pref";
@Override
public int getMetricsCategory() {
@@ -174,6 +175,7 @@
List<String> keys = super.getNonIndexableKeys(context);
// Duplicates in summary and details pages.
keys.add(KEY_TEXT_TO_SPEECH);
+ keys.add(KEY_PHYSICAL_KEYBOARD);
return keys;
}
diff --git a/src/com/android/settings/network/MobileNetworkPreferenceController.java b/src/com/android/settings/network/MobileNetworkPreferenceController.java
index d8b7745..6e2c2d5 100644
--- a/src/com/android/settings/network/MobileNetworkPreferenceController.java
+++ b/src/com/android/settings/network/MobileNetworkPreferenceController.java
@@ -33,7 +33,6 @@
import static android.os.UserHandle.myUserId;
import static android.os.UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
-import static com.android.settingslib.RestrictedLockUtils.hasBaseUserRestriction;
public class MobileNetworkPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
@@ -42,22 +41,30 @@
private final boolean mIsSecondaryUser;
private final TelephonyManager mTelephonyManager;
+ private final UserManager mUserManager;
private Preference mPreference;
@VisibleForTesting
PhoneStateListener mPhoneStateListener;
public MobileNetworkPreferenceController(Context context) {
super(context);
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mIsSecondaryUser = !userManager.isAdminUser();
+ mIsSecondaryUser = !mUserManager.isAdminUser();
}
@Override
public boolean isAvailable() {
- return !mIsSecondaryUser
- && !Utils.isWifiOnly(mContext)
- && !hasBaseUserRestriction(mContext, DISALLOW_CONFIG_MOBILE_NETWORKS, myUserId());
+ return !isUserRestricted() && !Utils.isWifiOnly(mContext);
+ }
+
+ public boolean isUserRestricted() {
+ final RestrictedLockUtilsWrapper wrapper = new RestrictedLockUtilsWrapper();
+ return mIsSecondaryUser ||
+ wrapper.hasBaseUserRestriction(
+ mContext,
+ DISALLOW_CONFIG_MOBILE_NETWORKS,
+ myUserId());
}
@Override
diff --git a/src/com/android/settings/network/RestrictedLockUtilsWrapper.java b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..de5b808
--- /dev/null
+++ b/src/com/android/settings/network/RestrictedLockUtilsWrapper.java
@@ -0,0 +1,15 @@
+package com.android.settings.network;
+
+import android.content.Context;
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Wrapper class needed to be able to test classes which use RestrictedLockUtils methods.
+ * Unfortunately there is no way to deal with this until robolectric is updated due to the fact
+ * that it is a static method and it uses new API's.
+ */
+public class RestrictedLockUtilsWrapper {
+ public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+ return RestrictedLockUtils.hasBaseUserRestriction(context, userRestriction, userId);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 5bda1ad..14ee779 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -98,6 +98,7 @@
// Turn NFC on/off
final boolean desiredState = (Boolean) value;
+ mSwitch.setChecked(desiredState);
mSwitch.setEnabled(false);
if (desiredState) {
diff --git a/src/com/android/settings/nfc/NfcPaymentPreference.java b/src/com/android/settings/nfc/NfcPaymentPreference.java
index 239377d..a3f7466 100644
--- a/src/com/android/settings/nfc/NfcPaymentPreference.java
+++ b/src/com/android/settings/nfc/NfcPaymentPreference.java
@@ -18,6 +18,7 @@
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
+import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.preference.PreferenceViewHolder;
@@ -209,7 +210,9 @@
if (!appInfo.isDefault) {
mPaymentBackend.setDefaultPaymentApp(appInfo.componentName);
}
- getDialog().dismiss();
+ Dialog dialog = getDialog();
+ if (dialog != null)
+ dialog.dismiss();
}
}
}
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index fa6c8ee..2f95dd2 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -351,7 +351,9 @@
if (mRingtone != null) {
mRingtone.onActivityResult(requestCode, resultCode, data);
}
- mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+ if (mChannel != null) {
+ mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
+ }
}
boolean canPulseLight() {
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 1428116..89f1e27 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -21,6 +21,7 @@
import android.media.AudioManager;
import android.net.Uri;
import android.preference.SeekBarVolumizer;
+import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.PreferenceViewHolder;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -51,30 +52,38 @@
private int mIconResId;
private int mMuteIconResId;
private boolean mStopped;
+ @VisibleForTesting
+ AudioManager mAudioManager;
public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutResource(R.layout.preference_volume_slider);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
public VolumeSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setLayoutResource(R.layout.preference_volume_slider);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
public VolumeSeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.preference_volume_slider);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
public VolumeSeekBarPreference(Context context) {
super(context);
setLayoutResource(R.layout.preference_volume_slider);
+ mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
public void setStream(int stream) {
mStream = stream;
+ setMax(mAudioManager.getStreamMaxVolume(mStream));
+ setProgress(mAudioManager.getStreamVolume(mStream));
}
public void setCallback(Callback callback) {
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 4d20bcf..5126727 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -219,7 +219,7 @@
mManagedPasswordProvider = ManagedLockPasswordProvider.get(getActivity(), mUserId);
if (mPasswordConfirmed) {
- updatePreferencesOrFinish();
+ updatePreferencesOrFinish(savedInstanceState != null);
if (mForChangeCredRequiredForBoot) {
maybeEnableEncryption(mLockPatternUtils.getKeyguardStoredPasswordQuality(
mUserId), false);
@@ -234,7 +234,7 @@
|| !helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)) {
mPasswordConfirmed = true; // no password set, so no need to confirm
- updatePreferencesOrFinish();
+ updatePreferencesOrFinish(savedInstanceState != null);
} else {
mWaitingForConfirmation = true;
}
@@ -332,7 +332,7 @@
if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
mPasswordConfirmed = true;
mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
- updatePreferencesOrFinish();
+ updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (mForChangeCredRequiredForBoot) {
if (!TextUtils.isEmpty(mUserPassword)) {
maybeEnableEncryption(
@@ -395,7 +395,7 @@
outState.putBoolean(ENCRYPT_REQUESTED_DISABLED, mEncryptionRequestDisabled);
}
- private void updatePreferencesOrFinish() {
+ private void updatePreferencesOrFinish(boolean isRecreatingActivity) {
Intent intent = getActivity().getIntent();
int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
if (quality == -1) {
@@ -413,7 +413,8 @@
updatePreferenceText();
updateCurrentPreference();
updatePreferenceSummaryIfNeeded();
- } else {
+ } else if (!isRecreatingActivity) {
+ // Don't start the activity again if we are recreated for configuration change
updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
}
}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index e013b8b..d890956 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -162,7 +162,7 @@
.getBooleanExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
CharSequence msg = getText(forFingerprint
? R.string.lockpassword_choose_your_password_header_for_fingerprint
- : R.string.lockpassword_choose_your_password_header);
+ : R.string.lockpassword_choose_your_screen_lock_header);
setTitle(msg);
LinearLayout layout = (LinearLayout) findViewById(R.id.content_parent);
layout.setFitsSystemWindows(false);
@@ -213,6 +213,7 @@
protected Button mCancelButton;
private Button mClearButton;
private Button mNextButton;
+ private TextView mMessage;
private TextChangedHandler mTextChangedHandler;
@@ -247,10 +248,14 @@
protected enum Stage {
Introduction(
- R.string.lockpassword_choose_your_password_header,
+ R.string.lockpassword_choose_your_screen_lock_header,
R.string.lockpassword_choose_your_password_header_for_fingerprint,
- R.string.lockpassword_choose_your_pin_header,
+ R.string.lockpassword_choose_your_screen_lock_header,
R.string.lockpassword_choose_your_pin_header_for_fingerprint,
+ R.string.lockpassword_choose_your_password_message,
+ R.string.lock_settings_picker_fingerprint_added_security_message,
+ R.string.lockpassword_choose_your_pin_message,
+ R.string.lock_settings_picker_fingerprint_added_security_message,
R.string.next_label),
NeedToConfirm(
@@ -258,6 +263,10 @@
R.string.lockpassword_confirm_your_password_header,
R.string.lockpassword_confirm_your_pin_header,
R.string.lockpassword_confirm_your_pin_header,
+ 0,
+ 0,
+ 0,
+ 0,
R.string.lockpassword_ok_label),
ConfirmWrong(
@@ -265,14 +274,25 @@
R.string.lockpassword_confirm_passwords_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
R.string.lockpassword_confirm_pins_dont_match,
+ 0,
+ 0,
+ 0,
+ 0,
R.string.next_label);
Stage(int hintInAlpha, int hintInAlphaForFingerprint,
- int hintInNumeric, int hintInNumericForFingerprint, int nextButtonText) {
+ int hintInNumeric, int hintInNumericForFingerprint,
+ int messageInAlpha, int messageInAlphaForFingerprint,
+ int messageInNumeric, int messageInNumericForFingerprint,
+ int nextButtonText) {
this.alphaHint = hintInAlpha;
this.alphaHintForFingerprint = hintInAlphaForFingerprint;
this.numericHint = hintInNumeric;
this.numericHintForFingerprint = hintInNumericForFingerprint;
+ this.alphaMessage = messageInAlpha;
+ this.alphaMessageForFingerprint = messageInAlphaForFingerprint;
+ this.numericMessage = messageInNumeric;
+ this.numericMessageForFingerprint = messageInNumericForFingerprint;
this.buttonText = nextButtonText;
}
@@ -280,6 +300,10 @@
public final int alphaHintForFingerprint;
public final int numericHint;
public final int numericHintForFingerprint;
+ public final int alphaMessage;
+ public final int alphaMessageForFingerprint;
+ public final int numericMessage;
+ public final int numericMessageForFingerprint;
public final int buttonText;
public @StringRes int getHint(boolean isAlpha, boolean isFingerprint) {
@@ -289,6 +313,14 @@
return isFingerprint ? numericHintForFingerprint : numericHint;
}
}
+
+ public @StringRes int getMessage(boolean isAlpha, boolean isFingerprint) {
+ if (isAlpha) {
+ return isFingerprint ? alphaMessageForFingerprint : alphaMessage;
+ } else {
+ return isFingerprint ? numericMessageForFingerprint : numericMessage;
+ }
+ }
}
// required constructor for fragments
@@ -351,14 +383,9 @@
mClearButton = view.findViewById(R.id.clear_button);
mClearButton.setOnClickListener(this);
+
+ mMessage = view.findViewById(R.id.message);
if (mForFingerprint) {
- TextView fingerprintBackupMessage =
- view.findViewById(R.id.fingerprint_backup_message);
- if (fingerprintBackupMessage != null) {
- fingerprintBackupMessage.setVisibility(View.VISIBLE);
- fingerprintBackupMessage
- .setText(R.string.setup_lock_settings_picker_fingerprint_message);
- }
mLayout.setIcon(getActivity().getDrawable(R.drawable.ic_fingerprint_header));
}
@@ -848,6 +875,13 @@
setNextEnabled(canInput && length > 0);
mClearButton.setEnabled(canInput && length > 0);
}
+ int message = mUiStage.getMessage(mIsAlphaMode, mForFingerprint);
+ if (message != 0) {
+ mMessage.setVisibility(View.VISIBLE);
+ mMessage.setText(message);
+ } else {
+ mMessage.setVisibility(View.INVISIBLE);
+ }
mClearButton.setVisibility(toVisibility(mUiStage != Stage.Introduction));
mCancelButton.setVisibility(toVisibility(mUiStage == Stage.Introduction));
diff --git a/src/com/android/settings/search/DynamicIndexableContentMonitor.java b/src/com/android/settings/search/DynamicIndexableContentMonitor.java
deleted file mode 100644
index a0e3c02..0000000
--- a/src/com/android/settings/search/DynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.search;
-
-import android.accessibilityservice.AccessibilityService;
-import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-import android.view.inputmethod.InputMethod;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.print.PrintSettingsFragment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public final class DynamicIndexableContentMonitor implements
- LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
- // Shorten the class name because log TAG can be at most 23 chars.
- private static final String TAG = "DynamicContentMonitor";
-
- private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
- // A PackageMonitor shared among Settings activities.
- private static final PackageChangeMonitor PACKAGE_CHANGE_MONITOR = new PackageChangeMonitor();
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private Context mContext;
- private boolean mHasFeaturePrinting;
-
- @VisibleForTesting
- static Intent getAccessibilityServiceIntent(String packageName) {
- final Intent intent = new Intent(AccessibilityService.SERVICE_INTERFACE);
- intent.setPackage(packageName);
- return intent;
- }
-
- @VisibleForTesting
- static Intent getIMEServiceIntent(String packageName) {
- final Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
- intent.setPackage(packageName);
- return intent;
- }
-
- @VisibleForTesting
- static void resetForTesting() {
- InputDevicesMonitor.getInstance().resetForTesting();
- InputMethodServicesMonitor.getInstance().resetForTesting();
- }
-
- /**
- * This instance holds a set of content monitor singleton objects.
- *
- * This object is created every time a sub-settings that extends {@code SettingsActivity}
- * is created.
- */
- public DynamicIndexableContentMonitor() {}
-
- /**
- * Creates and initializes a set of content monitor singleton objects if not yet exist.
- * Also starts loading the list of print services.
- * <code>mIndex</code> has non-null value after successfully initialized.
- *
- * @param activity used to get {@link LoaderManager}.
- * @param loaderId id for loading print services.
- */
- public void register(Activity activity, int loaderId) {
- final boolean isUserUnlocked = activity
- .getSystemService(UserManager.class)
- .isUserUnlocked();
- register(activity, loaderId, FeatureFactory.getFactory(activity)
- .getSearchFeatureProvider().getIndexingManager(activity), isUserUnlocked);
- }
-
- /**
- * For testing to inject {@link DatabaseIndexingManager} object.
- * Also because currently Robolectric doesn't support API 24, we can not test code that calls
- * {@link UserManager#isUserUnlocked()}.
- */
- @VisibleForTesting
- void register(Activity activity, int loaderId, DatabaseIndexingManager indexManager,
- boolean isUserUnlocked) {
- if (!isUserUnlocked) {
- Log.w(TAG, "Skipping content monitoring because user is locked");
- return;
- }
- final Context context = activity.getApplicationContext();
- mContext = context;
- mIndexManager = indexManager;
-
- PACKAGE_CHANGE_MONITOR.registerMonitor(context);
- mHasFeaturePrinting = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_PRINTING);
- if (mHasFeaturePrinting) {
- activity.getLoaderManager().initLoader(loaderId, null /* args */, this /* callbacks */);
- }
-
- // Watch for input device changes.
- InputDevicesMonitor.getInstance().initialize(context, mIndexManager);
-
- // Start tracking packages.
- InputMethodServicesMonitor.getInstance().initialize(context, mIndexManager);
- }
-
- /**
- * Aborts loading the list of print services.
- * Note that a set of content monitor singletons keep alive while Settings app is running.
- *
- * @param activity user to get {@link LoaderManager}.
- * @param loaderId id for loading print services.
- */
- public void unregister(Activity activity, int loaderId) {
- if (mIndexManager == null) return;
-
- PACKAGE_CHANGE_MONITOR.unregisterMonitor();
- if (mHasFeaturePrinting) {
- activity.getLoaderManager().destroyLoader(loaderId);
- }
- }
-
- @Override
- public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
- return new PrintServicesLoader(
- (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE), mContext,
- PrintManager.ALL_SERVICES);
- }
-
- @Override
- public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
- List<PrintServiceInfo> services) {
- mIndexManager.updateFromClassNameResource(PrintSettingsFragment.class.getName(),
- true /* includeInSearchResults */);
- }
-
- @Override
- public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
- // nothing to do
- }
-
- // A singleton that monitors input devices changes and updates indexes of physical keyboards.
- private static class InputDevicesMonitor implements InputManager.InputDeviceListener {
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private InputManager mInputManager;
-
- private InputDevicesMonitor() {}
-
- private static class SingletonHolder {
- private static final InputDevicesMonitor INSTANCE = new InputDevicesMonitor();
- }
-
- static InputDevicesMonitor getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- @VisibleForTesting
- synchronized void resetForTesting() {
- if (mIndexManager != null) {
- mInputManager.unregisterInputDeviceListener(this /* listener */);
- }
- mIndexManager = null;
- }
-
- synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
- if (mIndexManager != null) return;
- mIndexManager = indexManager;
- mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
- buildIndex();
-
- // Watch for input device changes.
- mInputManager.registerInputDeviceListener(this /* listener */, null /* handler */);
- }
-
- private void buildIndex() {
- mIndexManager.updateFromClassNameResource(PhysicalKeyboardFragment.class.getName(),
- true /* includeInSearchResults */);
- }
-
- @Override
- public void onInputDeviceAdded(int deviceId) {
- buildIndex();
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- buildIndex();
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- buildIndex();
- }
- }
-
- // A singleton that monitors package installing, uninstalling, enabling, and disabling.
- // Then updates indexes of accessibility services and input methods.
- private static class PackageChangeMonitor extends PackageMonitor {
- private static final String TAG = PackageChangeMonitor.class.getSimpleName();
-
- // Null if not initialized. Guarded by {@link #mLock}.
- @Nullable private PackageManager mPackageManager;
- private final Object mLock = new Object();
-
- public void registerMonitor(Context context) {
- synchronized (mLock) {
- if (mPackageManager != null) {
- return;
- }
- mPackageManager = context.getPackageManager();
-
- // Start tracking packages. Use background thread for monitoring. Note that no need
- // to unregister this monitor. This should be alive while Settings app is running.
- super.register(context, null /* thread */, UserHandle.CURRENT, false);
- }
- }
-
- public void unregisterMonitor() {
- synchronized (mLock) {
- if (mPackageManager == null) {
- return;
- }
- super.unregister();
- mPackageManager = null;
- }
- }
-
- // Covers installed, appeared external storage with the package, upgraded.
- @Override
- public void onPackageAppeared(String packageName, int reason) {
- postPackageAvailable(packageName);
- }
-
- // Covers uninstalled, removed external storage with the package.
- @Override
- public void onPackageDisappeared(String packageName, int reason) {
- postPackageUnavailable(packageName);
- }
-
- // Covers enabled, disabled.
- @Override
- public void onPackageModified(String packageName) {
- try {
- final int state = mPackageManager.getApplicationEnabledSetting(packageName);
- if (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- postPackageAvailable(packageName);
- } else {
- postPackageUnavailable(packageName);
- }
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Package does not exist: " + packageName, e);
- }
- }
-
- private void postPackageAvailable(final String packageName) {
- getRegisteredHandler().postDelayed(() -> {
- InputMethodServicesMonitor.getInstance().onPackageAvailable(packageName);
- }, DELAY_PROCESS_PACKAGE_CHANGE);
- }
-
- private void postPackageUnavailable(final String packageName) {
- getRegisteredHandler().postDelayed(() -> {
- InputMethodServicesMonitor.getInstance().onPackageUnavailable(packageName);
- }, DELAY_PROCESS_PACKAGE_CHANGE);
- }
- }
-
- // A singleton that holds list of available input methods and updates search index.
- // Also it monitors user dictionary changes and updates search index.
- private static class InputMethodServicesMonitor extends ContentObserver {
-
- private static final Uri ENABLED_INPUT_METHODS_CONTENT_URI =
- Settings.Secure.getUriFor(Settings.Secure.ENABLED_INPUT_METHODS);
-
- // Null if not initialized.
- @Nullable private DatabaseIndexingManager mIndexManager;
- private PackageManager mPackageManager;
- private ContentResolver mContentResolver;
- private final List<String> mInputMethodServices = new ArrayList<>();
-
- private InputMethodServicesMonitor() {
- // No need for handler because {@link #onChange(boolean,Uri)} is short and quick.
- super(null /* handler */);
- }
-
- private static class SingletonHolder {
- private static final InputMethodServicesMonitor INSTANCE =
- new InputMethodServicesMonitor();
- }
-
- static InputMethodServicesMonitor getInstance() {
- return SingletonHolder.INSTANCE;
- }
-
- @VisibleForTesting
- synchronized void resetForTesting() {
- if (mIndexManager != null) {
- mContentResolver.unregisterContentObserver(this /* observer */);
- }
- mIndexManager = null;
- }
-
- synchronized void initialize(Context context, DatabaseIndexingManager indexManager) {
- final boolean hasFeatureIme = context.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_INPUT_METHODS);
- if (!hasFeatureIme) return;
-
- if (mIndexManager != null) return;
- mIndexManager = indexManager;
- mPackageManager = context.getPackageManager();
- mContentResolver = context.getContentResolver();
- mInputMethodServices.clear();
- // Build index of {@link UserDictionary}.
- buildIndex(LanguageAndInputSettings.class);
- // Build index of IMEs.
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
-
- // Cache IME service packages to know when they go away.
- final InputMethodManager inputMethodManager = (InputMethodManager) context
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- for (final InputMethodInfo inputMethod : inputMethodManager.getInputMethodList()) {
- ServiceInfo serviceInfo = inputMethod.getServiceInfo();
- if (serviceInfo != null) {
- mInputMethodServices.add(serviceInfo.packageName);
- }
- }
-
- // TODO: Implements by JobScheduler with TriggerContentUri parameters.
- // Watch for related content URIs.
- mContentResolver.registerContentObserver(UserDictionary.Words.CONTENT_URI,
- true /* notifyForDescendants */, this /* observer */);
- // Watch for changing enabled IMEs.
- mContentResolver.registerContentObserver(ENABLED_INPUT_METHODS_CONTENT_URI,
- false /* notifyForDescendants */, this /* observer */);
- }
-
- private void buildIndex(Class<?> indexClass) {
- mIndexManager.updateFromClassNameResource(indexClass.getName(),
- true /* includeInSearchResults */);
- }
-
- synchronized void onPackageAvailable(String packageName) {
- if (mIndexManager == null) return;
- if (mInputMethodServices.contains(packageName)) return;
-
- final Intent intent = getIMEServiceIntent(packageName);
- final List<ResolveInfo> services = mPackageManager
- .queryIntentServices(intent, 0 /* flags */);
- if (services == null || services.isEmpty()) return;
- mInputMethodServices.add(packageName);
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- }
-
- synchronized void onPackageUnavailable(String packageName) {
- if (mIndexManager == null) return;
- if (!mInputMethodServices.remove(packageName)) return;
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- if (ENABLED_INPUT_METHODS_CONTENT_URI.equals(uri)) {
- buildIndex(VirtualKeyboardFragment.class);
- buildIndex(AvailableVirtualKeyboardFragment.class);
- } else if (UserDictionary.Words.CONTENT_URI.equals(uri)) {
- buildIndex(LanguageAndInputSettings.class);
- }
- }
- }
-}
diff --git a/src/com/android/settings/search/InputDeviceResultLoader.java b/src/com/android/settings/search/InputDeviceResultLoader.java
new file mode 100644
index 0000000..61e1ad1
--- /dev/null
+++ b/src/com/android/settings/search/InputDeviceResultLoader.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.search;
+
+import static android.content.Context.INPUT_METHOD_SERVICE;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.support.annotation.VisibleForTesting;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.SiteMapManager;
+import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
+import com.android.settings.inputmethod.PhysicalKeyboardFragment;
+import com.android.settings.utils.AsyncLoader;
+import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Search result for input devices (physical/virtual keyboard, game controllers, etc)
+ */
+public class InputDeviceResultLoader extends AsyncLoader<Set<? extends SearchResult>> {
+ private static final int NAME_NO_MATCH = -1;
+
+ @VisibleForTesting
+ static final String PHYSICAL_KEYBOARD_FRAGMENT = PhysicalKeyboardFragment.class.getName();
+ @VisibleForTesting
+ static final String VIRTUAL_KEYBOARD_FRAGMENT =
+ AvailableVirtualKeyboardFragment.class.getName();
+
+ private final SiteMapManager mSiteMapManager;
+ private final InputManager mInputManager;
+ private final InputMethodManager mImm;
+ private final PackageManager mPackageManager;
+ @VisibleForTesting
+ final String mQuery;
+
+ private List<String> mPhysicalKeyboardBreadcrumb;
+ private List<String> mVirtualKeyboardBreadcrumb;
+
+ public InputDeviceResultLoader(Context context, String query, SiteMapManager mapManager) {
+ super(context);
+ mQuery = query;
+ mSiteMapManager = mapManager;
+ mInputManager = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ mImm = (InputMethodManager) context.getSystemService(INPUT_METHOD_SERVICE);
+ mPackageManager = context.getPackageManager();
+ }
+
+ @Override
+ protected void onDiscardResult(Set<? extends SearchResult> result) {
+ }
+
+ @Override
+ public Set<? extends SearchResult> loadInBackground() {
+ final Set<SearchResult> results = new HashSet<>();
+ results.addAll(buildPhysicalKeyboardSearchResults());
+ results.addAll(buildVirtualKeyboardSearchResults());
+ return results;
+ }
+
+ private Set<SearchResult> buildPhysicalKeyboardSearchResults() {
+ final Set<SearchResult> results = new HashSet<>();
+ final Context context = getContext();
+ final String screenTitle = context.getString(R.string.physical_keyboard_title);
+
+ for (final InputDevice device : getPhysicalFullKeyboards()) {
+ final String deviceName = device.getName();
+ final int wordDiff = InstalledAppResultLoader.getWordDifference(deviceName, mQuery);
+ if (wordDiff == NAME_NO_MATCH) {
+ continue;
+ }
+ final String keyboardLayoutDescriptor = mInputManager
+ .getCurrentKeyboardLayoutForInputDevice(device.getIdentifier());
+ final KeyboardLayout keyboardLayout = (keyboardLayoutDescriptor != null)
+ ? mInputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
+ final String summary = (keyboardLayout != null)
+ ? keyboardLayout.toString()
+ : context.getString(R.string.keyboard_layout_default_label);
+ final String key = deviceName;
+
+ final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
+ PHYSICAL_KEYBOARD_FRAGMENT, key, screenTitle);
+ results.add(new SearchResult.Builder()
+ .setTitle(deviceName)
+ .setPayload(new ResultPayload(intent))
+ .setStableId(Objects.hash(PHYSICAL_KEYBOARD_FRAGMENT, key))
+ .setSummary(summary)
+ .setRank(wordDiff)
+ .addBreadcrumbs(getPhysicalKeyboardBreadCrumb())
+ .build());
+ }
+ return results;
+ }
+
+ private Set<SearchResult> buildVirtualKeyboardSearchResults() {
+ final Set<SearchResult> results = new HashSet<>();
+ final Context context = getContext();
+ final String screenTitle = context.getString(R.string.add_virtual_keyboard);
+ final List<InputMethodInfo> inputMethods = mImm.getInputMethodList();
+ for (InputMethodInfo info : inputMethods) {
+ final String title = info.loadLabel(mPackageManager).toString();
+ final String summary = InputMethodAndSubtypeUtil
+ .getSubtypeLocaleNameListAsSentence(getAllSubtypesOf(info), context, info);
+ int wordDiff = InstalledAppResultLoader.getWordDifference(title, mQuery);
+ if (wordDiff == NAME_NO_MATCH) {
+ wordDiff = InstalledAppResultLoader.getWordDifference(summary, mQuery);
+ }
+ if (wordDiff == NAME_NO_MATCH) {
+ continue;
+ }
+ final ServiceInfo serviceInfo = info.getServiceInfo();
+ final String key = new ComponentName(serviceInfo.packageName, serviceInfo.name)
+ .flattenToString();
+ final Intent intent = DatabaseIndexingUtils.buildSubsettingIntent(context,
+ VIRTUAL_KEYBOARD_FRAGMENT, key, screenTitle);
+ results.add(new SearchResult.Builder()
+ .setTitle(title)
+ .setSummary(summary)
+ .setRank(wordDiff)
+ .setStableId(Objects.hash(VIRTUAL_KEYBOARD_FRAGMENT, key))
+ .addBreadcrumbs(getVirtualKeyboardBreadCrumb())
+ .setPayload(new ResultPayload(intent))
+ .build());
+ }
+ return results;
+ }
+
+ private List<String> getPhysicalKeyboardBreadCrumb() {
+ if (mPhysicalKeyboardBreadcrumb == null || mPhysicalKeyboardBreadcrumb.isEmpty()) {
+ final Context context = getContext();
+ mPhysicalKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+ context, PHYSICAL_KEYBOARD_FRAGMENT,
+ context.getString(R.string.physical_keyboard_title));
+ }
+ return mPhysicalKeyboardBreadcrumb;
+ }
+
+
+ private List<String> getVirtualKeyboardBreadCrumb() {
+ if (mVirtualKeyboardBreadcrumb == null || mVirtualKeyboardBreadcrumb.isEmpty()) {
+ final Context context = getContext();
+ mVirtualKeyboardBreadcrumb = mSiteMapManager.buildBreadCrumb(
+ context, VIRTUAL_KEYBOARD_FRAGMENT,
+ context.getString(R.string.add_virtual_keyboard));
+ }
+ return mVirtualKeyboardBreadcrumb;
+ }
+
+ private List<InputDevice> getPhysicalFullKeyboards() {
+ final List<InputDevice> keyboards = new ArrayList<>();
+ final int[] deviceIds = InputDevice.getDeviceIds();
+ if (deviceIds != null) {
+ for (int deviceId : deviceIds) {
+ final InputDevice device = InputDevice.getDevice(deviceId);
+ if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
+ keyboards.add(device);
+ }
+ }
+ }
+ return keyboards;
+ }
+
+ private static List<InputMethodSubtype> getAllSubtypesOf(final InputMethodInfo imi) {
+ final int subtypeCount = imi.getSubtypeCount();
+ final List<InputMethodSubtype> allSubtypes = new ArrayList<>(subtypeCount);
+ for (int index = 0; index < subtypeCount; index++) {
+ allSubtypes.add(imi.getSubtypeAt(index));
+ }
+ return allSubtypes;
+ }
+}
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 7e0e086..900cefc 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -49,6 +49,11 @@
String query);
/**
+ * Returns a new loader to search input devices.
+ */
+ InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query);
+
+ /**
* Returns a new loader to get all recently saved queries search terms.
*/
SavedQueryLoader getSavedQueryLoader(Context context);
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index b90547e..400cf8f 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -62,6 +62,11 @@
}
@Override
+ public InputDeviceResultLoader getInputDeviceResultLoader(Context context, String query) {
+ return new InputDeviceResultLoader(context, cleanQuery(query), getSiteMapManager());
+ }
+
+ @Override
public SavedQueryLoader getSavedQueryLoader(Context context) {
return new SavedQueryLoader(context);
}
diff --git a/src/com/android/settings/search/SearchFragment.java b/src/com/android/settings/search/SearchFragment.java
index fb89d6e..ccc4d61 100644
--- a/src/com/android/settings/search/SearchFragment.java
+++ b/src/com/android/settings/search/SearchFragment.java
@@ -84,8 +84,10 @@
static final int LOADER_ID_INSTALLED_APPS = 2;
@VisibleForTesting
static final int LOADER_ID_ACCESSIBILITY_SERVICES = 3;
+ @VisibleForTesting
+ static final int LOADER_ID_INPUT_DEVICES = 4;
- private static final int NUM_QUERY_LOADERS = 3;
+ private static final int NUM_QUERY_LOADERS = 4;
@VisibleForTesting
AtomicInteger mUnfinishedLoadersCount = new AtomicInteger(NUM_QUERY_LOADERS);
@@ -284,6 +286,7 @@
loaderManager.destroyLoader(LOADER_ID_DATABASE);
loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
loaderManager.destroyLoader(LOADER_ID_ACCESSIBILITY_SERVICES);
+ loaderManager.destroyLoader(LOADER_ID_INPUT_DEVICES);
mShowingSavedQuery = true;
mSavedQueryController.loadSavedQueries();
mSearchFeatureProvider.hideFeedbackButton();
@@ -314,6 +317,8 @@
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
case LOADER_ID_ACCESSIBILITY_SERVICES:
return mSearchFeatureProvider.getAccessibilityServiceResultLoader(activity, mQuery);
+ case LOADER_ID_INPUT_DEVICES:
+ return mSearchFeatureProvider.getInputDeviceResultLoader(activity, mQuery);
default:
return null;
}
@@ -351,6 +356,8 @@
LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
loaderManager.initLoader(
LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */, this /* callback */);
+ loaderManager.initLoader(
+ LOADER_ID_INPUT_DEVICES, null /* args */, this /* callback */);
}
requery();
@@ -392,6 +399,8 @@
loaderManager.restartLoader(LOADER_ID_INSTALLED_APPS, null /* args */, this /* callback */);
loaderManager.restartLoader(LOADER_ID_ACCESSIBILITY_SERVICES, null /* args */,
this /* callback */);
+ loaderManager.restartLoader(LOADER_ID_INPUT_DEVICES, null /* args */,
+ this /* callback */);
}
public String getQuery() {
diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java
index 6c58a0d..7b886a4 100644
--- a/src/com/android/settings/search/SearchResultsAdapter.java
+++ b/src/com/android/settings/search/SearchResultsAdapter.java
@@ -57,7 +57,9 @@
@VisibleForTesting
static final String APP_RESULTS_LOADER_KEY = InstalledAppResultLoader.class.getName();
@VisibleForTesting
- static final String ACCESSIBLITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+ static final String ACCESSIBILITY_LOADER_KEY = AccessibilityServiceResultLoader.class.getName();
+ @VisibleForTesting
+ static final String INPUT_DEVICE_LOADER_KEY = InputDeviceResultLoader.class.getName();
@VisibleForTesting
static final int MSG_RANKING_TIMED_OUT = 1;
@@ -265,17 +267,21 @@
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
List<? extends SearchResult> accessibilityResults =
- getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+ getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+ List<? extends SearchResult> inputDeviceResults =
+ getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
int dbSize = databaseResults.size();
int appSize = installedAppResults.size();
int a11ySize = accessibilityResults.size();
-
+ int inputDeviceSize = inputDeviceResults.size();
int dbIndex = 0;
int appIndex = 0;
int a11yIndex = 0;
+ int inputDeviceIndex = 0;
int rank = SearchResult.TOP_RANK;
+ // TODO: We need a helper method to do k-way merge.
mStaticallyRankedSearchResults.clear();
while (rank <= SearchResult.BOTTOM_RANK) {
while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) {
@@ -287,6 +293,10 @@
while ((a11yIndex < a11ySize) && (accessibilityResults.get(a11yIndex).rank == rank)) {
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
}
+ while (inputDeviceIndex < inputDeviceSize
+ && inputDeviceResults.get(inputDeviceIndex).rank == rank) {
+ mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+ }
rank++;
}
@@ -299,6 +309,9 @@
while(a11yIndex < a11ySize) {
mStaticallyRankedSearchResults.add(accessibilityResults.get(a11yIndex++));
}
+ while (inputDeviceIndex < inputDeviceSize) {
+ mStaticallyRankedSearchResults.add(inputDeviceResults.get(inputDeviceIndex++));
+ }
}
private void updateSearchResults() {
@@ -332,12 +345,16 @@
List<? extends SearchResult> installedAppResults =
getSortedLoadedResults(APP_RESULTS_LOADER_KEY);
List<? extends SearchResult> accessibilityResults =
- getSortedLoadedResults(ACCESSIBLITY_LOADER_KEY);
+ getSortedLoadedResults(ACCESSIBILITY_LOADER_KEY);
+ List<? extends SearchResult> inputDeviceResults =
+ getSortedLoadedResults(INPUT_DEVICE_LOADER_KEY);
int dbSize = databaseResults.size();
int appSize = installedAppResults.size();
int a11ySize = accessibilityResults.size();
+ int inputDeviceSize = inputDeviceResults.size();
- final List<SearchResult> asyncRankingResults = new ArrayList<>(dbSize + appSize + a11ySize);
+ final List<SearchResult> asyncRankingResults = new ArrayList<>(
+ dbSize + appSize + a11ySize + inputDeviceSize);
TreeSet<SearchResult> dbResultsSortedByScores = new TreeSet<>(
new Comparator<SearchResult>() {
@Override
@@ -358,13 +375,13 @@
// Other results are not ranked by async ranking and appended at the end of the list.
asyncRankingResults.addAll(installedAppResults);
asyncRankingResults.addAll(accessibilityResults);
+ asyncRankingResults.addAll(inputDeviceResults);
return asyncRankingResults;
}
@VisibleForTesting
Set<? extends SearchResult> getUnsortedLoadedResults(String loaderKey) {
- return mResultsMap.containsKey(loaderKey) ?
- mResultsMap.get(loaderKey) : new HashSet<SearchResult>();
+ return mResultsMap.containsKey(loaderKey) ? mResultsMap.get(loaderKey) : new HashSet<>();
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
index 78bc7d1..69a1351 100644
--- a/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/SetupChooseLockPatternTest.java
@@ -30,7 +30,6 @@
import com.android.settings.password.SetupChooseLockPattern;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -49,7 +48,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
index 92aa675..8ed7284 100644
--- a/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/ManageApplicationsTest.java
@@ -16,6 +16,17 @@
package com.android.settings.applications;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -35,7 +46,6 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.widget.LoadingViewController;
import com.android.settingslib.applications.ApplicationsState;
@@ -53,17 +63,6 @@
import java.util.ArrayList;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
/**
* Tests for {@link ManageApplications}.
*/
@@ -74,7 +73,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class
})
public class ManageApplicationsTest {
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java b/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java
new file mode 100644
index 0000000..fd46b4b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/AlwaysDiscoverableTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AlwaysDiscoverableTest {
+ @Mock
+ private LocalBluetoothAdapter mLocalAdapter;
+
+ @Mock
+ private Context mContext;
+
+ private AlwaysDiscoverable mAlwaysDiscoverable;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter);
+ }
+
+ @Test
+ public void isStartedWithoutStart() {
+ assertThat(mAlwaysDiscoverable.mStarted).isFalse();
+ }
+
+ @Test
+ public void isStartedWithStart() {
+ mAlwaysDiscoverable.start();
+ assertThat(mAlwaysDiscoverable.mStarted).isTrue();
+ }
+
+ @Test
+ public void isStartedWithStartStop() {
+ mAlwaysDiscoverable.start();
+ mAlwaysDiscoverable.stop();
+ assertThat(mAlwaysDiscoverable.mStarted).isFalse();
+ }
+
+ @Test
+ public void stopWithoutStart() {
+ mAlwaysDiscoverable.stop();
+ // expect no crash
+ verify(mLocalAdapter, never()).setScanMode(anyInt());
+ }
+
+ @Test
+ public void startSetsModeAndRegistersReceiver() {
+ when(mLocalAdapter.getScanMode()).thenReturn(BluetoothAdapter.SCAN_MODE_NONE);
+ mAlwaysDiscoverable.start();
+ verify(mLocalAdapter).setScanMode(eq(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
+ verify(mContext).registerReceiver(eq(mAlwaysDiscoverable), any());
+ }
+
+ @Test
+ public void stopUnregistersReceiver() {
+ mAlwaysDiscoverable.start();
+ mAlwaysDiscoverable.stop();
+ verify(mContext).unregisterReceiver(mAlwaysDiscoverable);
+ }
+
+ @Test
+ public void resetsToDiscoverableModeWhenScanModeChanges() {
+ mAlwaysDiscoverable.start();
+ verify(mLocalAdapter, times(1)).setScanMode(
+ BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+ sendScanModeChangedIntent(BluetoothAdapter.SCAN_MODE_CONNECTABLE,
+ BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+
+ verify(mLocalAdapter, times(2)).setScanMode(
+ BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+ }
+
+ private void sendScanModeChangedIntent(int newMode, int previousMode) {
+ when(mLocalAdapter.getScanMode()).thenReturn(newMode);
+ Intent intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
+ intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, newMode);
+ intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE, previousMode);
+ mAlwaysDiscoverable.onReceive(mContext, intent);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
index c4772e5..d1d4935 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
@@ -85,6 +85,7 @@
mFragment.mLocalAdapter = mLocalAdapter;
mFragment.mLocalManager = mLocalManager;
mFragment.mDeviceListGroup = mPreferenceGroup;
+ mFragment.mAlwaysDiscoverable = new AlwaysDiscoverable(mContext, mLocalAdapter);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
index 7a6ae79..fba11de 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java
@@ -28,6 +28,7 @@
import static org.mockito.Mockito.when;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.Context;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -47,6 +48,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.FragmentTestUtil;
@@ -412,6 +414,39 @@
verify(dialogActivity, times(1)).dismiss();
}
+ @Test
+ public void rotateDialog_nullPinText_okButtonEnabled() {
+ userEntryDialogExistingTextTest(null);
+ }
+
+ @Test
+ public void rotateDialog_emptyPinText_okButtonEnabled() {
+ userEntryDialogExistingTextTest("");
+ }
+
+ @Test
+ public void rotateDialog_nonEmptyPinText_okButtonEnabled() {
+ userEntryDialogExistingTextTest("test");
+ }
+
+ // Runs a test simulating the user entry dialog type in a situation like device rotation, where
+ // the dialog fragment gets created and we already have some existing text entered into the
+ // pin field.
+ private void userEntryDialogExistingTextTest(CharSequence existingText) {
+ when(controller.getDialogType()).thenReturn(BluetoothPairingController.USER_ENTRY_DIALOG);
+ when(controller.getDeviceVariantMessageHintId())
+ .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
+ when(controller.getDeviceVariantMessageId())
+ .thenReturn(BluetoothPairingController.INVALID_DIALOG_TYPE);
+
+ BluetoothPairingDialogFragment fragment = spy(new BluetoothPairingDialogFragment());
+ when(fragment.getPairingViewText()).thenReturn(existingText);
+ setupFragment(fragment);
+ AlertDialog dialog = ShadowAlertDialog.getLatestAlertDialog();
+ boolean expected = !TextUtils.isEmpty(existingText);
+ assertThat(dialog.getButton(Dialog.BUTTON_POSITIVE).isEnabled()).isEqualTo(expected);
+ }
+
private void setupFragment(BluetoothPairingDialogFragment frag) {
assertThat(frag.isPairingControllerSet()).isFalse();
frag.setPairingController(controller);
diff --git a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
index ec644a6..bb41cf0 100644
--- a/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/tests/robotests/src/com/android/settings/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -39,7 +39,7 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
- .FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE;
+ .FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
import static org.mockito.Matchers.any;
@@ -88,7 +88,7 @@
verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
argThat(mNamePairMatcher),
- argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, Long.class)));
+ argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
}
@Test
@@ -103,10 +103,10 @@
verify(mMetricsFeature).action(any(Context.class), anyInt(),
argThat(mNamePairMatcher),
- argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, true)));
+ argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
argThat(mNamePairMatcher),
- argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, false)));
+ argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
}
@Test
@@ -120,7 +120,33 @@
verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
argThat(mNamePairMatcher),
- argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_LONG_VALUE, Long.class)));
+ argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+ }
+
+ @Test
+ public void putLong_biggerThanIntMax_shouldLogIntMax() {
+ final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+ final long veryBigNumber = 500L + Integer.MAX_VALUE;
+ editor.putLong(TEST_KEY, 1);
+ editor.putLong(TEST_KEY, veryBigNumber);
+
+ verify(mMetricsFeature).action(any(Context.class), anyInt(),
+ argThat(mNamePairMatcher),
+ argThat(pairMatches(
+ FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+ }
+
+ @Test
+ public void putLong_smallerThanIntMin_shouldLogIntMin() {
+ final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+ final long veryNegativeNumber = -500L + Integer.MIN_VALUE;
+ editor.putLong(TEST_KEY, 1);
+ editor.putLong(TEST_KEY, veryNegativeNumber);
+
+ verify(mMetricsFeature).action(any(Context.class), anyInt(),
+ argThat(mNamePairMatcher),
+ argThat(pairMatches(
+ FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
}
@Test
@@ -152,7 +178,13 @@
private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
return pair -> pair.first == tag
- && Platform.isInstanceOfType(pair.second, Long.class)
- && pair.second.equals((bool ? 1L : 0L));
+ && Platform.isInstanceOfType(pair.second, Integer.class)
+ && pair.second.equals((bool ? 1 : 0));
+ }
+
+ private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
+ return pair -> pair.first == tag
+ && Platform.isInstanceOfType(pair.second, Integer.class)
+ && pair.second.equals(val);
}
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
index 8a8a13d..6b56c29 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java
@@ -15,6 +15,19 @@
*/
package com.android.settings.dashboard;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -38,7 +51,6 @@
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
@@ -56,26 +68,12 @@
import java.util.ArrayList;
import java.util.List;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class DashboardAdapterTest {
diff --git a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
index 344914a..ad52bf6 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -36,7 +36,6 @@
import com.android.settings.password.IFingerprintManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -61,7 +60,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index f1b7ee0..ce31328 100644
--- a/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -30,7 +30,6 @@
import com.android.settings.password.IFingerprintManager;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -53,7 +52,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
@@ -97,7 +95,7 @@
AlertDialog alertDialog = ShadowAlertDialog.getLatestAlertDialog();
assertNotNull(alertDialog);
ShadowAlertDialog shadowAlertDialog = Shadows.shadowOf(alertDialog);
- int titleRes = R.string.fingerprint_enroll_skip_after_adding_lock_title;
+ int titleRes = R.string.setup_fingerprint_enroll_skip_title;
assertEquals(application.getString(titleRes), shadowAlertDialog.getTitle());
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
index 013d379..e434bb3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceControllerTest.java
@@ -17,6 +17,15 @@
package com.android.settings.fuelgauge;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -27,11 +36,10 @@
import android.widget.TextView;
import com.android.settings.R;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.LayoutPreference;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -45,23 +53,12 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doReturn;
-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,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEntityHeaderController.class
})
public class BatteryHeaderPreferenceControllerTest {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
index e3a94d2..3a1fad0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
@@ -16,15 +16,17 @@
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.ColorFilter;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import org.junit.Before;
import org.junit.Test;
@@ -34,10 +36,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
@RunWith(SettingsRobolectricTestRunner.class)
// TODO: Consider making the shadow class set global using a robolectric.properties file.
@Config(manifest = TestConfig.MANIFEST_PATH,
@@ -45,7 +43,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class BatteryMeterViewTest {
private static final int BATTERY_LEVEL = 100;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 83e630d..48a48b1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -18,9 +18,7 @@
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
-
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
@@ -34,8 +32,6 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.List;
-
import android.app.LoaderManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -68,7 +64,6 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settingslib.core.AbstractPreferenceController;
import org.junit.Before;
@@ -95,7 +90,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class
})
public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
similarity index 70%
rename from tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
index b2d3596..6767346 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGesturePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsPreferenceControllerTest.java
@@ -16,9 +16,6 @@
package com.android.settings.gestures;
-import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED;
-
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -26,17 +23,16 @@
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
-
import android.provider.Settings.Secure;
+
import com.android.settings.TestConfig;
-import com.android.settings.display.AutoBrightnessPreferenceController;
import com.android.settings.search.InlinePayload;
import com.android.settings.search.InlineSwitchPayload;
import com.android.settings.search.ResultPayload;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
import com.android.settings.testutils.shadow.ShadowSecureSettings;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,16 +41,15 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class AssistGesturePreferenceControllerTest {
+public class AssistGestureSettingsPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private FakeFeatureFactory mFactory;
- private AssistGesturePreferenceController mController;
+ private AssistGestureSettingsPreferenceController mController;
private static final String KEY_ASSIST = "gesture_assist";
@@ -63,7 +58,8 @@
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(mContext);
mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
- mController = new AssistGesturePreferenceController(mContext, null, KEY_ASSIST, false);
+ mController = new AssistGestureSettingsPreferenceController(mContext, null, KEY_ASSIST,
+ false);
}
@Test
@@ -80,31 +76,11 @@
}
@Test
- public void testSwitchEnabled_configIsSet_shouldReturnTrue() {
- // Set the setting to be enabled.
- final Context context = ShadowApplication.getInstance().getApplicationContext();
- Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 1);
- mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST, false);
-
- assertThat(mController.isSwitchPrefEnabled()).isTrue();
- }
-
- @Test
- public void testSwitchEnabled_configIsNotSet_shouldReturnFalse() {
- // Set the setting to be disabled.
- final Context context = ShadowApplication.getInstance().getApplicationContext();
- Settings.System.putInt(context.getContentResolver(), ASSIST_GESTURE_ENABLED, 0);
- mController = new AssistGesturePreferenceController(context, null, KEY_ASSIST, false);
-
- assertThat(mController.isSwitchPrefEnabled()).isFalse();
- }
-
- @Test
public void testPreferenceController_ProperResultPayloadType() {
final Context context = RuntimeEnvironment.application;
- AssistGesturePreferenceController controller =
- new AssistGesturePreferenceController(context, null /* lifecycle */, KEY_ASSIST,
- false /* assistOnly */);
+ AssistGestureSettingsPreferenceController controller =
+ new AssistGestureSettingsPreferenceController(context, null /* lifecycle */,
+ KEY_ASSIST, false /* assistOnly */);
ResultPayload payload = controller.getResultPayload();
assertThat(payload).isInstanceOf(InlineSwitchPayload.class);
}
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
index cfd3f52..1f5c9be 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
@@ -62,13 +62,6 @@
}
@Test
- public void testGetPreferenceControllers_shouldAllBeCreated() {
- final List<AbstractPreferenceController> controllers =
- mSettings.getPreferenceControllers(mContext);
- assertThat(controllers.isEmpty()).isFalse();
- }
-
- @Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
AssistGestureSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
index 3b92ed1..d4fc014 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java
@@ -129,46 +129,6 @@
assertThat(mController.isSwitchPrefEnabled()).isFalse();
}
- @Test
- public void testPreferenceController_ProperResultPayloadType() {
- when(mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys))
- .thenReturn(true);
-
- SwipeToNotificationPreferenceController controller =
- new SwipeToNotificationPreferenceController(mContext, null /* lifecycle */,
- SYSTEM_NAVIGATION_KEYS_ENABLED);
- ResultPayload payload = controller.getResultPayload();
- assertThat(payload).isInstanceOf(InlineSwitchPayload.class);
- }
-
- @Test
- @Config(shadows = ShadowSecureSettings.class)
- public void testSetValue_updatesCorrectly() {
- int newValue = 1;
- ContentResolver resolver = mContext.getContentResolver();
- Settings.Secure.putInt(resolver, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0);
-
- ((InlinePayload) mController.getResultPayload()).setValue(mContext, newValue);
- int updatedValue = Settings.Secure.getInt(resolver,
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, -1);
-
- assertThat(updatedValue).isEqualTo(newValue);
- }
-
- @Test
- @Config(shadows = ShadowSecureSettings.class)
- public void testGetValue_correctValueReturned() {
- int currentValue = 1;
- ContentResolver resolver = mContext.getContentResolver();
- Settings.Secure.putInt(resolver,
- Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, currentValue);
-
- int newValue = ((InlinePayload) mController.getResultPayload()).getValue(mContext);
-
- assertThat(newValue).isEqualTo(currentValue);
- }
-
private void stubFingerprintSupported(boolean enabled) {
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
.thenReturn(enabled);
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
index e115dad..66e357b 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkPreferenceControllerTest.java
@@ -26,6 +26,7 @@
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsWrapper;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -87,6 +88,7 @@
}
@Test
+ @Config(shadows = ShadowRestrictedLockUtilsWrapper.class)
public void wifiOnly_prefIsNotAvailable() {
when(mUserManager.isAdminUser()).thenReturn(true);
when(mUserManager.hasUserRestriction(anyString(), any(UserHandle.class)))
diff --git a/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
new file mode 100644
index 0000000..b091cd3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/VolumeSeekBarPreferenceTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.notification;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VolumeSeekBarPreferenceTest {
+
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private VolumeSeekBarPreference mPreference;
+ @Mock
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
+ mPreference.mAudioManager = mAudioManager;
+ }
+
+ @Test
+ public void setStream_shouldSetMaxAndProgress() {
+ final int stream = 5;
+ final int max = 17;
+ final int progress = 4;
+ when(mAudioManager.getStreamMaxVolume(stream)).thenReturn(max);
+ when(mAudioManager.getStreamVolume(stream)).thenReturn(progress);
+ doCallRealMethod().when(mPreference).setStream(anyInt());
+
+ mPreference.setStream(stream);
+
+ verify(mPreference).setMax(max);
+ verify(mPreference).setProgress(progress);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 5fa731e..b8f0679 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -31,7 +31,6 @@
import com.android.settings.password.ChooseLockPassword.IntentBuilder;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.setupwizardlib.GlifLayout;
@@ -52,7 +51,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
index b238049..c74448b 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPatternTest.java
@@ -29,7 +29,6 @@
import com.android.settings.password.ChooseLockPattern.IntentBuilder;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.setupwizardlib.GlifLayout;
@@ -48,7 +47,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
index 39a0fb6..1195a2c 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPasswordTest.java
@@ -34,7 +34,6 @@
import com.android.settings.password.SetupChooseLockPassword.SetupChooseLockPasswordFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -62,7 +61,6 @@
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
index 639349d..0e6f28a 100644
--- a/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupSkipDialogTest.java
@@ -27,7 +27,6 @@
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
-import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settings.testutils.shadow.ShadowEventLogWriter;
import com.android.settings.testutils.shadow.ShadowUtils;
@@ -40,13 +39,11 @@
import org.robolectric.shadows.ShadowAlertDialog;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
- manifest = TestConfig.MANIFEST_PATH,
+@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {
SettingsShadowResources.class,
SettingsShadowResources.SettingsShadowTheme.class,
- ShadowDynamicIndexableContentMonitor.class,
ShadowEventLogWriter.class,
ShadowUtils.class
})
diff --git a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java b/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
deleted file mode 100644
index 26c89d5..0000000
--- a/tests/robotests/src/com/android/settings/search/DynamicIndexableContentMonitorTest.java
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.search;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Activity;
-import android.app.Application;
-import android.app.LoaderManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.hardware.input.InputManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.print.PrintManager;
-import android.print.PrintServicesLoader;
-import android.printservice.PrintServiceInfo;
-import android.provider.Settings;
-import android.provider.UserDictionary;
-import android.view.inputmethod.InputMethodInfo;
-
-import com.android.internal.content.PackageMonitor;
-import com.android.settings.TestConfig;
-import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
-import com.android.settings.inputmethod.PhysicalKeyboardFragment;
-import com.android.settings.inputmethod.VirtualKeyboardFragment;
-import com.android.settings.language.LanguageAndInputSettings;
-import com.android.settings.print.PrintSettingsFragment;
-import com.android.settings.testutils.DatabaseTestUtils;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowActivityWithLoadManager;
-import com.android.settings.testutils.shadow.ShadowContextImplWithRegisterReceiver;
-import com.android.settings.testutils.shadow.ShadowInputManager;
-import com.android.settings.testutils.shadow.ShadowInputMethodManagerWithMethodList;
-import com.android.settings.testutils.shadow.ShadowPackageMonitor;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-import org.robolectric.internal.ShadowExtractor;
-import org.robolectric.res.builder.RobolectricPackageManager;
-import org.robolectric.shadows.ShadowAccessibilityManager;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowContentResolver;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
- manifest = TestConfig.MANIFEST_PATH,
- sdk = TestConfig.SDK_VERSION,
- shadows = {
- ShadowActivityWithLoadManager.class,
- ShadowContextImplWithRegisterReceiver.class,
- ShadowInputManager.class,
- ShadowInputMethodManagerWithMethodList.class,
- ShadowPackageMonitor.class,
- }
-)
-public class DynamicIndexableContentMonitorTest {
-
- private static final int LOADER_ID = 1234;
- private static final String A11Y_PACKAGE_1 = "a11y-1";
- private static final String A11Y_PACKAGE_2 = "a11y-2";
- private static final String IME_PACKAGE_1 = "ime-1";
- private static final String IME_PACKAGE_2 = "ime-2";
-
- @Mock
- private LoaderManager mLoaderManager;
- @Mock
- private DatabaseIndexingManager mIndexManager;
-
- private Activity mActivity;
- private InputManager mInputManager;
-
- private ShadowContextImplWithRegisterReceiver mShadowContextImpl;
- private ShadowActivityWithLoadManager mShadowActivity;
- private ShadowAccessibilityManager mShadowAccessibilityManager;
- private ShadowInputMethodManagerWithMethodList mShadowInputMethodManager;
- private RobolectricPackageManager mRobolectricPackageManager;
-
- private final DynamicIndexableContentMonitor mMonitor = new DynamicIndexableContentMonitor();
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mActivity = Robolectric.buildActivity(Activity.class).get();
- mInputManager = InputManager.getInstance();
-
- // Robolectric shadows.
- mShadowContextImpl = (ShadowContextImplWithRegisterReceiver) ShadowExtractor.extract(
- ((Application) ShadowApplication.getInstance().getApplicationContext())
- .getBaseContext());
- mShadowActivity = (ShadowActivityWithLoadManager) ShadowExtractor.extract(mActivity);
- mShadowAccessibilityManager = (ShadowAccessibilityManager) ShadowExtractor.extract(
- mActivity.getSystemService(Context.ACCESSIBILITY_SERVICE));
- mShadowInputMethodManager = (ShadowInputMethodManagerWithMethodList) ShadowExtractor
- .extract(mActivity.getSystemService(Context.INPUT_METHOD_SERVICE));
- mRobolectricPackageManager = RuntimeEnvironment.getRobolectricPackageManager();
-
- // Setup shadows.
- mShadowContextImpl.setSystemService(Context.PRINT_SERVICE, mock(PrintManager.class));
- mShadowContextImpl.setSystemService(Context.INPUT_SERVICE, mInputManager);
- mShadowActivity.setLoaderManager(mLoaderManager);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(Collections.emptyList());
- mShadowInputMethodManager.setInputMethodList(Collections.emptyList());
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, true);
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_INPUT_METHODS, true);
- }
-
- @After
- public void shutDown() {
- mMonitor.unregister(mActivity, LOADER_ID);
- // BroadcastReceiver must be unregistered.
- assertThat(extractPackageMonitor()).isNull();
-
- DynamicIndexableContentMonitor.resetForTesting();
- mRobolectricPackageManager.reset();
-
- DatabaseTestUtils.clearDb(mActivity);
- }
-
- @Test
- public void testLockedUser() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, false /* isUserUnlocked */);
-
- // No loader procedure happens.
- verify(mLoaderManager, never()).initLoader(
- anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
- // No indexing happens.
- verify(mIndexManager, never()).updateFromClassNameResource(
- anyString(), anyBoolean());
-
- mMonitor.unregister(mActivity, LOADER_ID);
-
- // No destroy loader should happen.
- verify(mLoaderManager, never()).destroyLoader(anyInt());
- }
-
- @Test
- public void testWithNoPrintingFeature() {
- mRobolectricPackageManager.setSystemFeature(PackageManager.FEATURE_PRINTING, false);
-
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // No loader procedure happens.
- verify(mLoaderManager, never()).initLoader(
- anyInt(), any(Bundle.class), any(LoaderManager.LoaderCallbacks.class));
- verifyNoIndexing(PrintSettingsFragment.class);
-
- mMonitor.unregister(mActivity, LOADER_ID);
-
- // No destroy loader should happen.
- verify(mLoaderManager, never()).destroyLoader(anyInt());
- // BroadcastReceiver must be unregistered.
- assertThat(extractPackageMonitor()).isNull();
-
- // To suppress spurious test fail in {@link #shutDown()}.
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
- }
-
- @Test
- public void testPrinterServiceIndex() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Loader procedure happens.
- verify(mLoaderManager, only()).initLoader(LOADER_ID, null, mMonitor);
-
- // Loading print services happens.
- final Loader<List<PrintServiceInfo>> loader =
- mMonitor.onCreateLoader(LOADER_ID, null /* args */);
- assertThat(loader).isInstanceOf(PrintServicesLoader.class);
- verifyNoIndexing(PrintSettingsFragment.class);
-
- mMonitor.onLoadFinished(loader, Collections.emptyList());
-
- verifyIncrementalIndexing(PrintSettingsFragment.class);
- }
-
- @Test
- public void testInputDevicesMonitor() {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Rebuild indexing should happen.
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
- // Input monitor should be registered to InputManager.
- final InputManager.InputDeviceListener listener = extactInputDeviceListener();
- assertThat(listener).isNotNull();
-
- /*
- * Nothing happens on successive register calls.
- */
- mMonitor.unregister(mActivity, LOADER_ID);
- reset(mIndexManager);
-
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- verifyNoIndexing(PhysicalKeyboardFragment.class);
- assertThat(extactInputDeviceListener()).isEqualTo(listener);
-
- /*
- * A device is added.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceAdded(1 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
- /*
- * A device is removed.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceRemoved(2 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
-
- /*
- * A device is changed.
- */
- reset(mIndexManager);
-
- listener.onInputDeviceChanged(3 /* deviceId */);
-
- verifyIncrementalIndexing(PhysicalKeyboardFragment.class);
- }
-
- @Test
- public void testInputMethodServicesMonitor() throws Exception {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- final Uri enabledInputMethodsContentUri = Settings.Secure.getUriFor(
- Settings.Secure.ENABLED_INPUT_METHODS);
- // Content observer should be registered.
- final ContentObserver observer = extractContentObserver(enabledInputMethodsContentUri);
- assertThat(observer).isNotNull();
-
- /*
- * When an input method service package is installed, incremental indexing happen.
- */
- reset(mIndexManager);
-
- installInputMethodService(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When another input method service package is installed, incremental indexing happens.
- */
- reset(mIndexManager);
-
- installInputMethodService(IME_PACKAGE_2);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service is disabled, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- disableInstalledPackage(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service is enabled, incremental indexing happens.
- */
- reset(mIndexManager);
-
- enableInstalledPackage(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an input method service package is uninstalled, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- uninstallInputMethodService(IME_PACKAGE_1);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When an accessibility service package is installed, nothing happens.
- */
- reset(mIndexManager);
-
- installAccessibilityService(A11Y_PACKAGE_1);
-
- verifyNoIndexing(VirtualKeyboardFragment.class);
- verifyNoIndexing(AvailableVirtualKeyboardFragment.class);
-
- /*
- * When enabled IMEs list is changed, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- observer.onChange(false /* selfChange */, enabledInputMethodsContentUri);
-
- verifyIncrementalIndexing(VirtualKeyboardFragment.class);
- verifyIncrementalIndexing(AvailableVirtualKeyboardFragment.class);
- }
-
- @Test
- public void testUserDictionaryChangeMonitor() throws Exception {
- mMonitor.register(mActivity, LOADER_ID, mIndexManager, true /* isUserUnlocked */);
-
- // Content observer should be registered.
- final ContentObserver observer = extractContentObserver(UserDictionary.Words.CONTENT_URI);
- assertThat(observer).isNotNull();
-
- verifyIncrementalIndexing(LanguageAndInputSettings.class);
-
- /*
- * When user dictionary content is changed, rebuild indexing happens.
- */
- reset(mIndexManager);
-
- observer.onChange(false /* selfChange */, UserDictionary.Words.CONTENT_URI);
-
- verifyIncrementalIndexing(LanguageAndInputSettings.class);
- }
-
- /*
- * Verification helpers.
- */
-
- private void verifyNoIndexing(Class<?> indexingClass) {
- verify(mIndexManager, never()).updateFromClassNameResource(eq(indexingClass.getName()),
- anyBoolean());
- }
-
- private void verifyIncrementalIndexing(Class<?> indexingClass) {
- verify(mIndexManager, times(1)).updateFromClassNameResource(indexingClass.getName(),
- true /* includeInSearchResults */);
- verify(mIndexManager, never()).updateFromClassNameResource(indexingClass.getName(),
- false /* includeInSearchResults */);
- }
-
- /*
- * Testing helper methods.
- */
-
- private InputManager.InputDeviceListener extactInputDeviceListener() {
- List<InputManager.InputDeviceListener> listeners = ((ShadowInputManager) ShadowExtractor
- .extract(mInputManager))
- .getRegisteredInputDeviceListeners();
- InputManager.InputDeviceListener inputDeviceListener = null;
- for (InputManager.InputDeviceListener listener : listeners) {
- if (isUnderTest(listener)) {
- if (inputDeviceListener != null) {
- assertThat(listener).isEqualTo(inputDeviceListener);
- } else {
- inputDeviceListener = listener;
- }
- }
- }
- return inputDeviceListener;
- }
-
- private PackageMonitor extractPackageMonitor() {
- List<ShadowApplication.Wrapper> receivers = ShadowApplication.getInstance()
- .getRegisteredReceivers();
- PackageMonitor packageMonitor = null;
- for (ShadowApplication.Wrapper wrapper : receivers) {
- BroadcastReceiver receiver = wrapper.getBroadcastReceiver();
- if (isUnderTest(receiver) && receiver instanceof PackageMonitor) {
- if (packageMonitor != null) {
- assertThat(receiver).isEqualTo(packageMonitor);
- } else {
- packageMonitor = (PackageMonitor) receiver;
- }
- }
- }
- return packageMonitor;
- }
-
- private ContentObserver extractContentObserver(Uri uri) {
- ShadowContentResolver contentResolver = (ShadowContentResolver) ShadowExtractor
- .extract(mActivity.getContentResolver());
- Collection<ContentObserver> observers = contentResolver.getContentObservers(uri);
- ContentObserver contentObserver = null;
- for (ContentObserver observer : observers) {
- if (isUnderTest(observer)) {
- if (contentObserver != null) {
- assertThat(observer).isEqualTo(contentObserver);
- } else {
- contentObserver = observer;
- }
- }
- }
- return contentObserver;
- }
-
- private void enableInstalledPackage(String packageName) {
- ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
- packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0 /* flags */);
- extractPackageMonitor().onPackageModified(packageName);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void disableInstalledPackage(String packageName) {
- ((PackageManager) mRobolectricPackageManager).setApplicationEnabledSetting(
- packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0 /* flags */);
- extractPackageMonitor().onPackageModified(packageName);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void installAccessibilityService(String packageName) throws Exception {
- final AccessibilityServiceInfo serviceToAdd = buildAccessibilityServiceInfo(packageName);
-
- final List<AccessibilityServiceInfo> services = new ArrayList<>();
- services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
- services.add(serviceToAdd);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
- final Intent intent = DynamicIndexableContentMonitor
- .getAccessibilityServiceIntent(packageName);
- mRobolectricPackageManager.addResolveInfoForIntent(intent, serviceToAdd.getResolveInfo());
- mRobolectricPackageManager.addPackage(packageName);
-
- extractPackageMonitor()
- .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void uninstallAccessibilityService(String packageName) throws Exception {
- final AccessibilityServiceInfo serviceToRemove = buildAccessibilityServiceInfo(packageName);
-
- final List<AccessibilityServiceInfo> services = new ArrayList<>();
- services.addAll(mShadowAccessibilityManager.getInstalledAccessibilityServiceList());
- services.remove(serviceToRemove);
- mShadowAccessibilityManager.setInstalledAccessibilityServiceList(services);
-
- final Intent intent = DynamicIndexableContentMonitor
- .getAccessibilityServiceIntent(packageName);
- mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
- mRobolectricPackageManager.removePackage(packageName);
-
- extractPackageMonitor()
- .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void installInputMethodService(String packageName) throws Exception {
- final ResolveInfo resolveInfoToAdd = buildResolveInfo(packageName, "imeService");
- final InputMethodInfo serviceToAdd = buildInputMethodInfo(resolveInfoToAdd);
-
- final List<InputMethodInfo> services = new ArrayList<>();
- services.addAll(mShadowInputMethodManager.getInputMethodList());
- services.add(serviceToAdd);
- mShadowInputMethodManager.setInputMethodList(services);
-
- final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
- mRobolectricPackageManager.addResolveInfoForIntent(intent, resolveInfoToAdd);
- mRobolectricPackageManager.addPackage(packageName);
-
- extractPackageMonitor()
- .onPackageAppeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private void uninstallInputMethodService(String packageName) throws Exception {
- final ResolveInfo resolveInfoToRemove = buildResolveInfo(packageName, "imeService");
- final InputMethodInfo serviceToRemove = buildInputMethodInfo(resolveInfoToRemove);
-
- final List<InputMethodInfo> services = new ArrayList<>();
- services.addAll(mShadowInputMethodManager.getInputMethodList());
- services.remove(serviceToRemove);
- mShadowInputMethodManager.setInputMethodList(services);
-
- final Intent intent = DynamicIndexableContentMonitor.getIMEServiceIntent(packageName);
- mRobolectricPackageManager.removeResolveInfosForIntent(intent, packageName);
- mRobolectricPackageManager.removePackage(packageName);
-
- extractPackageMonitor()
- .onPackageDisappeared(packageName, PackageMonitor.PACKAGE_PERMANENT_CHANGE);
- Robolectric.flushBackgroundThreadScheduler();
- }
-
- private AccessibilityServiceInfo buildAccessibilityServiceInfo(String packageName)
- throws IOException, XmlPullParserException {
- return new AccessibilityServiceInfo(
- buildResolveInfo(packageName, "A11yService"), mActivity);
- }
-
- private static InputMethodInfo buildInputMethodInfo(ResolveInfo resolveInfo) {
- return new InputMethodInfo(resolveInfo, false /* isAuxIme */, "SettingsActivity",
- null /* subtypes */, 0 /* defaultResId */, false /* forceDefault */);
- }
-
- private static ResolveInfo buildResolveInfo(String packageName, String className) {
- final ResolveInfo resolveInfo = new ResolveInfo();
- resolveInfo.serviceInfo = new ServiceInfo();
- resolveInfo.serviceInfo.packageName = packageName;
- resolveInfo.serviceInfo.name = className;
- // To workaround that RobolectricPackageManager.removeResolveInfosForIntent() only works
- // for activity/broadcast resolver.
- resolveInfo.activityInfo = new ActivityInfo();
- resolveInfo.activityInfo.packageName = packageName;
- resolveInfo.activityInfo.name = className;
-
- return resolveInfo;
- }
-
- private static boolean isUnderTest(Object object) {
- return object.getClass().getName().startsWith(
- DynamicIndexableContentMonitor.class.getName());
- }
-}
diff --git a/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
new file mode 100644
index 0000000..a955af1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/InputDeviceResultLoaderTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.search;
+
+import static android.content.Context.INPUT_METHOD_SERVICE;
+import static com.android.settings.search.InputDeviceResultLoader.PHYSICAL_KEYBOARD_FRAGMENT;
+import static com.android.settings.search.InputDeviceResultLoader.VIRTUAL_KEYBOARD_FRAGMENT;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.hardware.input.InputManager;
+import android.view.InputDevice;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.dashboard.SiteMapManager;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowInputDevice;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ ShadowInputDevice.class
+ })
+public class InputDeviceResultLoaderTest {
+
+ private static final String QUERY = "test_query";
+ private static final List<String> PHYSICAL_KEYBOARD_BREADCRUMB;
+ private static final List<String> VIRTUAL_KEYBOARD_BREADCRUMB;
+
+ static {
+ PHYSICAL_KEYBOARD_BREADCRUMB = new ArrayList<>();
+ VIRTUAL_KEYBOARD_BREADCRUMB = new ArrayList<>();
+ PHYSICAL_KEYBOARD_BREADCRUMB.add("Settings");
+ PHYSICAL_KEYBOARD_BREADCRUMB.add("physical keyboard");
+ VIRTUAL_KEYBOARD_BREADCRUMB.add("Settings");
+ VIRTUAL_KEYBOARD_BREADCRUMB.add("virtual keyboard");
+ }
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private SiteMapManager mSiteMapManager;
+ @Mock
+ private InputManager mInputManager;
+ @Mock
+ private InputMethodManager mImm;
+ @Mock
+ private PackageManager mPackageManager;
+
+ private InputDeviceResultLoader mLoader;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mContext.getSystemService(Context.INPUT_SERVICE))
+ .thenReturn(mInputManager);
+ when(mContext.getSystemService(INPUT_METHOD_SERVICE))
+ .thenReturn(mImm);
+ when(mContext.getPackageManager())
+ .thenReturn(mPackageManager);
+ when(mContext.getString(anyInt()))
+ .thenAnswer(invocation -> RuntimeEnvironment.application.getString(
+ (Integer) invocation.getArguments()[0]));
+ mLoader = new InputDeviceResultLoader(mContext, QUERY, mSiteMapManager);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowInputDevice.reset();
+ }
+
+ @Test
+ public void query_noKeyboard_shouldNotReturnAnything() {
+ assertThat(mLoader.loadInBackground()).isEmpty();
+ }
+
+ @Test
+ public void query_hasPhysicalKeyboard_match() {
+ addPhysicalKeyboard(QUERY);
+ when(mSiteMapManager.buildBreadCrumb(mContext, PHYSICAL_KEYBOARD_FRAGMENT,
+ RuntimeEnvironment.application.getString(R.string.physical_keyboard_title)))
+ .thenReturn(PHYSICAL_KEYBOARD_BREADCRUMB);
+
+ final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).title).isEqualTo(QUERY);
+ assertThat(results.get(0).breadcrumbs)
+ .containsExactlyElementsIn(PHYSICAL_KEYBOARD_BREADCRUMB);
+ }
+
+ @Test
+ public void query_hasVirtualKeyboard_match() {
+ addVirtualKeyboard(QUERY);
+ when(mSiteMapManager.buildBreadCrumb(mContext, VIRTUAL_KEYBOARD_FRAGMENT,
+ RuntimeEnvironment.application.getString(R.string.add_virtual_keyboard)))
+ .thenReturn(VIRTUAL_KEYBOARD_BREADCRUMB);
+
+ final List<SearchResult> results = new ArrayList<>(mLoader.loadInBackground());
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).title).isEqualTo(QUERY);
+ assertThat(results.get(0).breadcrumbs)
+ .containsExactlyElementsIn(VIRTUAL_KEYBOARD_BREADCRUMB);
+ }
+
+ @Test
+ public void query_hasPhysicalVirtualKeyboard_doNotMatch() {
+ addPhysicalKeyboard("abc");
+ addVirtualKeyboard("def");
+
+ assertThat(mLoader.loadInBackground()).isEmpty();
+ verifyZeroInteractions(mSiteMapManager);
+ }
+
+ private void addPhysicalKeyboard(String name) {
+ final InputDevice device = mock(InputDevice.class);
+ when(device.isVirtual()).thenReturn(false);
+ when(device.isFullKeyboard()).thenReturn(true);
+ when(device.getName()).thenReturn(name);
+ ShadowInputDevice.sDeviceIds = new int[]{0};
+ ShadowInputDevice.addDevice(0, device);
+ }
+
+ private void addVirtualKeyboard(String name) {
+ final List<InputMethodInfo> imis = new ArrayList<>();
+ final InputMethodInfo info = mock(InputMethodInfo.class);
+ imis.add(info);
+ when(info.getServiceInfo()).thenReturn(new ServiceInfo());
+ when(info.loadLabel(mPackageManager)).thenReturn(name);
+ info.getServiceInfo().packageName = "pkg";
+ info.getServiceInfo().name = "class";
+ when(mImm.getInputMethodList()).thenReturn(imis);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
similarity index 88%
rename from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
rename to tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
index aa9b778..0a06a35 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockAccessibilityLoader.java
@@ -21,9 +21,9 @@
import java.util.HashSet;
import java.util.Set;
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
+public class MockAccessibilityLoader extends AccessibilityServiceResultLoader {
- public MockAccessiblityLoader(Context context) {
+ public MockAccessibilityLoader(Context context) {
super(context, "test_query", null);
}
diff --git a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
similarity index 88%
copy from tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
copy to tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
index aa9b778..2c16b14 100644
--- a/tests/robotests/src/com/android/settings/search/MockAccessiblityLoader.java
+++ b/tests/robotests/src/com/android/settings/search/MockInputDeviceResultLoader.java
@@ -21,9 +21,8 @@
import java.util.HashSet;
import java.util.Set;
-public class MockAccessiblityLoader extends AccessibilityServiceResultLoader {
-
- public MockAccessiblityLoader(Context context) {
+public class MockInputDeviceResultLoader extends InputDeviceResultLoader {
+ public MockInputDeviceResultLoader(Context context) {
super(context, "test_query", null);
}
diff --git a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
index 6588805..71c31aa 100644
--- a/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchFragmentTest.java
@@ -17,6 +17,20 @@
package com.android.settings.search;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.app.LoaderManager;
import android.content.Context;
import android.content.Intent;
@@ -28,10 +42,10 @@
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
@@ -52,20 +66,6 @@
import java.util.Set;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
@@ -83,6 +83,8 @@
private InstalledAppResultLoader mInstalledAppResultLoader;
@Mock
private AccessibilityServiceResultLoader mAccessibilityServiceResultLoader;
+ @Mock
+ private InputDeviceResultLoader mInputDeviceResultLoader;
@Mock
private SavedQueryLoader mSavedQueryLoader;
@@ -118,6 +120,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -178,6 +183,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -236,6 +244,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =
@@ -270,6 +281,9 @@
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
.thenReturn(mAccessibilityServiceResultLoader);
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(mInputDeviceResultLoader);
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
@@ -349,7 +363,10 @@
.thenReturn(new MockAppLoader(RuntimeEnvironment.application));
when(mFeatureFactory.searchFeatureProvider
.getAccessibilityServiceResultLoader(any(Context.class), anyString()))
- .thenReturn(new MockAccessiblityLoader(RuntimeEnvironment.application));
+ .thenReturn(new MockAccessibilityLoader(RuntimeEnvironment.application));
+ when(mFeatureFactory.searchFeatureProvider
+ .getInputDeviceResultLoader(any(Context.class), anyString()))
+ .thenReturn(new MockInputDeviceResultLoader(RuntimeEnvironment.application));
when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
.thenReturn(mSavedQueryLoader);
ActivityController<SearchActivity> activityController =
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
deleted file mode 100644
index de5d243..0000000
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDynamicIndexableContentMonitor.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.settings.testutils.shadow;
-
-import android.app.Activity;
-import android.os.UserManager;
-import com.android.settings.search.DynamicIndexableContentMonitor;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.annotation.RealObject;
-
-/**
- * A shadow class of {@link DynamicIndexableContentMonitor}. The real implementation of
- * {@link DynamicIndexableContentMonitor#register} calls {@link UserManager#isUserUnlocked()}, which
- * Robolectric has not yet been updated to support, so throws a NoSuchMethodError exception.
- */
-// TODO: Delete this once Robolectric is updated to the latest SDK.
-@Implements(DynamicIndexableContentMonitor.class)
-public class ShadowDynamicIndexableContentMonitor {
-
- @Implementation
- public void register(Activity activity, int loaderId) {
- }
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
new file mode 100644
index 0000000..8d76063
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowMobileNetworkPreferenceController.java
@@ -0,0 +1,28 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.MobileNetworkPreferenceController;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+@Implements(MobileNetworkPreferenceController.class)
+public class ShadowMobileNetworkPreferenceController {
+ private static boolean mIsRestricted = false;
+
+ public void __constructor__(Context context) {
+ }
+
+ @Implementation
+ public boolean isAvailable() {
+ return mIsRestricted ? false : true;
+ }
+
+ @Implementation
+ public boolean isUserRestricted() {
+ return mIsRestricted;
+ }
+
+ public static void setRestricted(boolean restricted) {
+ mIsRestricted = restricted;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
new file mode 100644
index 0000000..0e0adce
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsWrapper.java
@@ -0,0 +1,25 @@
+package com.android.settings.testutils.shadow;
+
+import android.content.Context;
+import com.android.settings.network.RestrictedLockUtilsWrapper;
+import org.robolectric.annotation.Implements;
+
+/**
+ * Shadow for the wrapper around RestrictedLockUtils. Should be removed/updated once robolectric is
+ * updated to allow usage of new UserManager API's. see
+ * {@link com.android.settingslib.RestrictedLockUtils} and
+ * {@link com.android.settings.network.RestrictedLockUtilsWrapper}
+ */
+@Implements(RestrictedLockUtilsWrapper.class)
+public class ShadowRestrictedLockUtilsWrapper {
+
+ private boolean isRestricted;
+
+ public boolean hasBaseUserRestriction(Context context, String userRestriction, int userId) {
+ return isRestricted;
+ }
+
+ public void setRestricted(boolean restricted) {
+ isRestricted = restricted;
+ }
+}