Merge "Convert DeviceInfoSettings into a dashboard fragment."
diff --git a/res/layout-land/choose_lock_pattern.xml b/res/layout-land/choose_lock_pattern.xml
index b4d5fce..0743577 100644
--- a/res/layout-land/choose_lock_pattern.xml
+++ b/res/layout-land/choose_lock_pattern.xml
@@ -39,6 +39,8 @@
android:layout_weight="1.0"
android:layout_marginStart="?attr/suwMarginSides"
android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<ImageView
@@ -86,7 +88,9 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dip"
- android:layout_weight="1.0">
+ android:layout_weight="1.0"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<!-- confirm / restart buttons -->
<LinearLayout android:id="@+id/buttonContainer"
@@ -94,6 +98,8 @@
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="horizontal">
<!-- left / top button: skip, or re-try -->
diff --git a/res/layout-land/fingerprint_enroll_enrolling.xml b/res/layout-land/fingerprint_enroll_enrolling.xml
index 27af681..c89bc42 100644
--- a/res/layout-land/fingerprint_enroll_enrolling.xml
+++ b/res/layout-land/fingerprint_enroll_enrolling.xml
@@ -40,6 +40,8 @@
android:layout_height="match_parent"
android:layout_marginStart="?attr/suwMarginSides"
android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<ImageView
diff --git a/res/layout-land/fingerprint_enroll_find_sensor.xml b/res/layout-land/fingerprint_enroll_find_sensor.xml
index b64b27f..3dadece 100644
--- a/res/layout-land/fingerprint_enroll_find_sensor.xml
+++ b/res/layout-land/fingerprint_enroll_find_sensor.xml
@@ -36,12 +36,16 @@
android:layout_height="match_parent"
android:layout_marginStart="?attr/suwMarginSides"
android:layout_marginBottom="@dimen/suw_content_frame_padding_bottom"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:clipChildren="false"
+ android:clipToPadding="false">
<ImageView
android:id="@+id/suw_layout_icon"
diff --git a/res/layout-land/fingerprint_enroll_finish.xml b/res/layout-land/fingerprint_enroll_finish.xml
index 664123d..5fc0d73 100644
--- a/res/layout-land/fingerprint_enroll_finish.xml
+++ b/res/layout-land/fingerprint_enroll_finish.xml
@@ -36,6 +36,8 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<TextView
@@ -59,6 +61,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="horizontal">
<Button
diff --git a/res/layout/choose_lock_password.xml b/res/layout/choose_lock_password.xml
index 4b9f3e5..15fb7db 100644
--- a/res/layout/choose_lock_password.xml
+++ b/res/layout/choose_lock_password.xml
@@ -26,6 +26,8 @@
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:gravity="center_horizontal"
android:orientation="vertical">
@@ -54,6 +56,8 @@
android:id="@+id/bottom_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
diff --git a/res/layout/choose_lock_pattern_common.xml b/res/layout/choose_lock_pattern_common.xml
index c50aa5b..050479b 100644
--- a/res/layout/choose_lock_pattern_common.xml
+++ b/res/layout/choose_lock_pattern_common.xml
@@ -29,6 +29,8 @@
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<!-- takes up all space above button bar at bottom -->
@@ -37,6 +39,8 @@
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<TextView android:id="@+id/headerText"
@@ -56,6 +60,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="horizontal">
<!-- left : cancel, or re-try -->
diff --git a/res/layout/fingerprint_enroll_finish_base.xml b/res/layout/fingerprint_enroll_finish_base.xml
index bcbbadf..99c96ad 100644
--- a/res/layout/fingerprint_enroll_finish_base.xml
+++ b/res/layout/fingerprint_enroll_finish_base.xml
@@ -75,6 +75,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="horizontal">
<Button
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index ccd1f62..6d20756 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -26,6 +26,8 @@
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<com.android.setupwizardlib.view.RichTextView
@@ -44,6 +46,8 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="horizontal">
<Button
diff --git a/res/layout/redaction_interstitial.xml b/res/layout/redaction_interstitial.xml
index d1ce0dc..e48f20f 100644
--- a/res/layout/redaction_interstitial.xml
+++ b/res/layout/redaction_interstitial.xml
@@ -28,6 +28,8 @@
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:orientation="vertical">
<TextView
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6885dcb..dfcbc96 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6229,13 +6229,13 @@
<string name="work_sound_same_as_personal">Same as personal profile</string>
<!-- Work Sound: Title for dialog shown when enabling sync with personal sounds. [CHAR LIMIT=60] -->
- <string name="work_sync_dialog_title">Replace work profile sounds?</string>
+ <string name="work_sync_dialog_title">Use personal profile sounds?</string>
- <!-- Work Sound: Confirm action text for dialog shown when enabling sync with personal sounds. [CHAR LIMIT=30] -->
+ <!-- Work Sound: Confirm action text for dialog shown when overriding work notification sounds with personal sounds. [CHAR LIMIT=30] -->
<string name="work_sync_dialog_yes">Replace</string>
- <!-- Work Sound: Message for dialog shown when enabling sync with personal sounds. [CHAR LIMIT=none] -->
- <string name="work_sync_dialog_message">Your current work profile sounds will be replaced with your personal profile sounds</string>
+ <!-- Work Sound: Message for dialog shown when using the same sounds for work events as for personal events (notifications / ringtones / alarms). [CHAR LIMIT=none] -->
+ <string name="work_sync_dialog_message">Your personal profile sounds will be used instead of your current work profile sounds</string>
<!-- Ringtones preference category: Title for the Ringotnes preference categories. [CHAR LIMIT=none] -->
<string name="ringtones_category_preference_title">Ringtones</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3f36255..790b726 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -259,13 +259,13 @@
<item name="android:singleLine">true</item>
</style>
- <style name="SetupWizardButton.Negative" parent="@android:style/Widget.Material.Button.Borderless.Colored">
- <item name="android:minWidth">0dp</item>
- <item name="android:textAllCaps">false</item>
- <item name="android:theme">@style/AccentColorHighlightBorderlessButton</item>
+ <style name="SetupWizardButton.Negative" parent="@style/SuwGlifButton.Secondary">
+ <!-- Negative margin to offset for padding of the button itself. We want the label to be
+ aligned with the text above it -->
+ <item name="android:layout_marginStart">-16dp</item>
</style>
- <style name="SetupWizardButton.Positive" parent="@android:style/Widget.Material.Button.Colored" />
+ <style name="SetupWizardButton.Positive" parent="@style/SuwGlifButton.Primary" />
<style name="AccentColorHighlightBorderlessButton">
<item name="android:colorControlHighlight">?android:attr/colorAccent</item>
diff --git a/res/xml/storage_dashboard_fragment.xml b/res/xml/storage_dashboard_fragment.xml
index 271d31b..fedc77f 100644
--- a/res/xml/storage_dashboard_fragment.xml
+++ b/res/xml/storage_dashboard_fragment.xml
@@ -16,40 +16,50 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/storage_settings">
+ android:title="@string/storage_settings"
+ android:orderingFromXml="false">
<com.android.settings.deviceinfo.storage.StorageSummaryDonutPreference
- android:key="pref_summary" />
+ android:key="pref_summary"
+ android:order="0" />
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_photos_videos"
- android:title="@string/storage_photos_videos">
+ android:title="@string/storage_photos_videos"
+ android:order="1" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_music_audio"
- android:title="@string/storage_music_audio">
+ android:title="@string/storage_music_audio"
+ android:order="2" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_games"
- android:title="@string/storage_games">
+ android:title="@string/storage_games"
+ android:order="3" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_other_apps"
- android:title="@string/storage_other_apps">
+ android:title="@string/storage_other_apps"
+ android:order="4" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_files"
- android:title="@string/storage_files">
+ android:title="@string/storage_files"
+ android:order="5" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
android:key="pref_system"
- android:title="@string/storage_detail_system">
+ android:title="@string/storage_detail_system"
+ android:order="100" >
</com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
<PreferenceCategory
android:key="pref_secondary_users"
- android:title="@string/storage_other_users" />
+ android:title="@string/storage_other_users"
+ android:order="200" />
<Preference
android:key="manage_storage"
android:title="@string/storage_menu_manage"
android:icon="@drawable/ic_settings_storage"
- android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
+ android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings"
+ android:order="300" >
</Preference>
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/storage_profile_fragment.xml b/res/xml/storage_profile_fragment.xml
new file mode 100644
index 0000000..d0c5c3a
--- /dev/null
+++ b/res/xml/storage_profile_fragment.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<!-- Layout for the storage breakdown for a profile of the primary user. -->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/storage_settings">
+ <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
+ android:key="pref_photos_videos"
+ android:title="@string/storage_photos_videos">
+ </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+ <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
+ android:key="pref_music_audio"
+ android:title="@string/storage_music_audio">
+ </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+ <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
+ android:key="pref_games"
+ android:title="@string/storage_games">
+ </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+ <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
+ android:key="pref_other_apps"
+ android:title="@string/storage_other_apps">
+ </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+ <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
+ android:key="pref_files"
+ android:title="@string/storage_files">
+ </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
+</PreferenceScreen>
diff --git a/src/com/android/settings/SmsDefaultDialog.java b/src/com/android/settings/SmsDefaultDialog.java
index 830187c..e4b49ee 100644
--- a/src/com/android/settings/SmsDefaultDialog.java
+++ b/src/com/android/settings/SmsDefaultDialog.java
@@ -125,6 +125,10 @@
p.mOnClickListener = this;
p.mNegativeButtonText = getString(R.string.cancel);
p.mNegativeButtonListener = this;
+ if (p.mAdapter.isEmpty()) {
+ // If there is nothing to choose from, don't build the dialog.
+ return false;
+ }
}
setupAlert();
diff --git a/src/com/android/settings/TetherService.java b/src/com/android/settings/TetherService.java
index 6d359f2..610d320 100644
--- a/src/com/android/settings/TetherService.java
+++ b/src/com/android/settings/TetherService.java
@@ -252,7 +252,8 @@
Intent intent = new Intent(provisionAction);
int type = mCurrentTethers.get(index);
intent.putExtra(TETHER_CHOICE, type);
- intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
return intent;
}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 124c441..350ab9c 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -65,6 +65,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.preference.PreferenceFrameLayout;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
@@ -1258,4 +1259,21 @@
(user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
&& user.profileGroupId == profile.profileGroupId);
}
+
+ /**
+ * Tries to initalize a volume with the given bundle. If it is a valid, private, and readable
+ * {@link VolumeInfo}, it is returned. If it is not valid, null is returned.
+ */
+ @Nullable
+ public static VolumeInfo maybeInitializeVolume(StorageManager sm, Bundle bundle) {
+ final String volumeId = bundle.getString(VolumeInfo.EXTRA_VOLUME_ID,
+ VolumeInfo.ID_PRIVATE_INTERNAL);
+ VolumeInfo volume = sm.findVolumeById(volumeId);
+ return isVolumeValid(volume) ? volume : null;
+ }
+
+ private static boolean isVolumeValid(VolumeInfo volume) {
+ return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
+ && volume.isMountedReadable();
+ }
}
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 878a044..db72fce 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -71,7 +71,6 @@
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.deviceinfo.storage.StorageStatsSource;
import com.android.settings.fuelgauge.HighPowerDetail;
import com.android.settings.fuelgauge.PowerWhitelistBackend;
import com.android.settings.notification.AppNotificationSettings;
@@ -85,6 +84,7 @@
import com.android.settingslib.applications.ApplicationsState.AppFilter;
import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
+import com.android.settingslib.applications.StorageStatsSource;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/src/com/android/settings/applications/MusicViewHolderController.java b/src/com/android/settings/applications/MusicViewHolderController.java
index fd7e320..d7c142f 100644
--- a/src/com/android/settings/applications/MusicViewHolderController.java
+++ b/src/com/android/settings/applications/MusicViewHolderController.java
@@ -26,7 +26,7 @@
import com.android.settings.R;
import com.android.settings.Utils;
-import com.android.settings.deviceinfo.storage.StorageStatsSource;
+import com.android.settingslib.applications.StorageStatsSource;
/**
* MusicViewHolderController controls an Audio/Music file view in the ManageApplications view.
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
index 7077912..9a5c224 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceController.java
@@ -39,7 +39,8 @@
@Override
public boolean isAvailable() {
- return true;
+ final List<ResolveInfo> candidates = getCandidates();
+ return candidates != null && !candidates.isEmpty();
}
@Override
@@ -61,16 +62,6 @@
}
}
- private String getOnlyAppLabel() {
- // Resolve that intent and check that the handleAllWebDataURI boolean is set
- final List<ResolveInfo> list = mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE,
- PackageManager.MATCH_ALL, mUserId);
- if (list != null && list.size() == 1) {
- return list.get(0).loadLabel(mPackageManager.getPackageManager()).toString();
- }
- return null;
- }
-
@Override
protected DefaultAppInfo getDefaultAppInfo() {
try {
@@ -81,6 +72,20 @@
}
}
+ private List<ResolveInfo> getCandidates() {
+ return mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE, PackageManager.MATCH_ALL,
+ mUserId);
+ }
+
+ private String getOnlyAppLabel() {
+ // Resolve that intent and check that the handleAllWebDataURI boolean is set
+ final List<ResolveInfo> list = getCandidates();
+ if (list != null && list.size() == 1) {
+ return list.get(0).loadLabel(mPackageManager.getPackageManager()).toString();
+ }
+ return null;
+ }
+
/**
* Whether or not the pkg contains browser capability
*/
diff --git a/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
index fa0d28f..8a73468 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultPhonePreferenceController.java
@@ -42,7 +42,11 @@
final boolean hasUserRestriction =
um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS);
- return !hasUserRestriction;
+ if (hasUserRestriction) {
+ return false;
+ }
+ final List<String> candidates = getCandidates();
+ return candidates != null && !candidates.isEmpty();
}
@Override
@@ -60,6 +64,10 @@
}
}
+ private List<String> getCandidates() {
+ return DefaultDialerManager.getInstalledDialerApplications(mContext, mUserId);
+ }
+
public static boolean hasPhonePreference(String pkg, Context context) {
List<String> dialerPackages =
DefaultDialerManager.getInstalledDialerApplications(context, UserHandle.myUserId());
diff --git a/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
index 0cee3c5..0792ff9 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
@@ -23,21 +23,26 @@
public class DefaultWorkBrowserPreferenceController extends DefaultBrowserPreferenceController {
+ private final UserHandle mUserHandle;
+
public DefaultWorkBrowserPreferenceController(Context context) {
super(context);
- final UserHandle managedProfile = Utils.getManagedProfile(mUserManager);
- if (managedProfile != null) {
- mUserId = managedProfile.getIdentifier();
+ mUserHandle = Utils.getManagedProfile(mUserManager);
+ if (mUserHandle != null) {
+ mUserId = mUserHandle.getIdentifier();
}
}
@Override
- public boolean isAvailable() {
- return Utils.getManagedProfile(mUserManager) != null;
- }
-
- @Override
public String getPreferenceKey() {
return "work_default_browser";
}
+
+ @Override
+ public boolean isAvailable() {
+ if (mUserHandle == null) {
+ return false;
+ }
+ return super.isAvailable();
+ }
}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
index f793fa3..c6d04fa 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
@@ -17,11 +17,28 @@
package com.android.settings.applications.defaultapps;
import android.content.Context;
+import android.os.UserHandle;
+
+import com.android.settings.Utils;
public class DefaultWorkPhonePreferenceController extends DefaultPhonePreferenceController {
+ private final UserHandle mUserHandle;
+
public DefaultWorkPhonePreferenceController(Context context) {
super(context);
+ mUserHandle = Utils.getManagedProfile(mUserManager);
+ if (mUserHandle != null) {
+ mUserId = mUserHandle.getIdentifier();
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (mUserHandle == null) {
+ return false;
+ }
+ return super.isAvailable();
}
@Override
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index d65eb75..72e1493 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -25,11 +25,11 @@
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.SearchIndexableResource;
-import android.support.annotation.VisibleForTesting;
import android.util.SparseArray;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.applications.PackageManagerWrapperImpl;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.applications.UserManagerWrapperImpl;
@@ -48,7 +48,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Map;
public class StorageDashboardFragment extends DashboardFragment
implements LoaderManager.LoaderCallbacks<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
@@ -61,11 +60,6 @@
private StorageItemPreferenceController mPreferenceController;
private List<PreferenceController> mSecondaryUsers;
- private boolean isVolumeValid() {
- return (mVolume != null) && (mVolume.getType() == VolumeInfo.TYPE_PRIVATE)
- && mVolume.isMountedReadable();
- }
-
@Override
public void onResume() {
super.onResume();
@@ -101,7 +95,8 @@
// Initialize the storage sizes that we can quickly calc.
final Context context = getActivity();
StorageManager sm = context.getSystemService(StorageManager.class);
- if (!initializeVolume(sm, getArguments())) {
+ mVolume = Utils.maybeInitializeVolume(sm, getArguments());
+ if (mVolume == null) {
getActivity().finish();
return;
}
@@ -157,30 +152,16 @@
}
/**
- * Initializes the volume with a given bundle and returns if the volume is valid.
- */
- @VisibleForTesting
- boolean initializeVolume(StorageManager sm, Bundle bundle) {
- String volumeId = bundle.getString(VolumeInfo.EXTRA_VOLUME_ID,
- VolumeInfo.ID_PRIVATE_INTERNAL);
- mVolume = sm.findVolumeById(volumeId);
- return isVolumeValid();
- }
-
- /**
* Updates the secondary user controller sizes.
*/
private void updateSecondaryUserControllers(List<PreferenceController> controllers,
SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
for (int i = 0, size = controllers.size(); i < size; i++) {
PreferenceController controller = controllers.get(i);
- if (controller instanceof SecondaryUserController) {
- SecondaryUserController userController = (SecondaryUserController) controller;
- int userId = userController.getUser().id;
- StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
- if (result != null) {
- userController.setSize(result.externalStats.totalBytes);
- }
+ if (controller instanceof StorageAsyncLoader.ResultHandler) {
+ StorageAsyncLoader.ResultHandler userController =
+ (StorageAsyncLoader.ResultHandler) controller;
+ userController.handleResult(stats);
}
}
}
diff --git a/src/com/android/settings/deviceinfo/StorageProfileFragment.java b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
new file mode 100644
index 0000000..6ae03da
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/StorageProfileFragment.java
@@ -0,0 +1,128 @@
+/*
+ * 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.deviceinfo;
+
+import android.app.LoaderManager;
+import android.content.Context;
+import android.content.Loader;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.util.SparseArray;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.PackageManagerWrapperImpl;
+import com.android.settings.applications.UserManagerWrapperImpl;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
+import com.android.settings.deviceinfo.storage.StorageAsyncLoader.AppsStorageResult;
+import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * StorageProfileFragment is a fragment which shows the storage results for a profile of the
+ * primary user.
+ */
+public class StorageProfileFragment extends DashboardFragment
+ implements LoaderManager.LoaderCallbacks<SparseArray<AppsStorageResult>> {
+ private static final String TAG = "StorageProfileFragment";
+ public static final String USER_ID_EXTRA = "userId";
+ private static final int APPS_JOB_ID = 0;
+
+ private VolumeInfo mVolume;
+ private int mUserId;
+ private StorageItemPreferenceController mPreferenceController;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final Bundle args = getArguments();
+
+ // Initialize the storage sizes that we can quickly calc.
+ final Context context = getActivity();
+ final StorageManager sm = context.getSystemService(StorageManager.class);
+ mVolume = Utils.maybeInitializeVolume(sm, args);
+ if (mVolume == null) {
+ getActivity().finish();
+ return;
+ }
+
+ mPreferenceController.setVolume(mVolume);
+ mUserId = args.getInt(USER_ID_EXTRA, UserHandle.myUserId());
+ mPreferenceController.setUserId(mUserId);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ getLoaderManager().initLoader(APPS_JOB_ID, Bundle.EMPTY, this);
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SETTINGS_STORAGE_PROFILE;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.storage_profile_fragment;
+ }
+
+ @Override
+ protected List<PreferenceController> getPreferenceControllers(Context context) {
+ final List<PreferenceController> controllers = new ArrayList<>();
+ final StorageManager sm = context.getSystemService(StorageManager.class);
+ mPreferenceController = new StorageItemPreferenceController(context, this,
+ mVolume, new StorageManagerVolumeProvider(sm));
+ controllers.add(mPreferenceController);
+ return controllers;
+ }
+
+ @Override
+ public Loader<SparseArray<AppsStorageResult>> onCreateLoader(int id, Bundle args) {
+ Context context = getContext();
+ return new StorageAsyncLoader(context,
+ new UserManagerWrapperImpl(context.getSystemService(UserManager.class)),
+ mVolume.fsUuid,
+ new StorageStatsSource(context),
+ new PackageManagerWrapperImpl(context.getPackageManager()));
+ }
+
+ @Override
+ public void onLoadFinished(Loader<SparseArray<AppsStorageResult>> loader,
+ SparseArray<AppsStorageResult> result) {
+ mPreferenceController.onLoadFinished(result.get(mUserId));
+ }
+
+ @Override
+ public void onLoaderReset(Loader<SparseArray<AppsStorageResult>> loader) {
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
index d45c6e3..a5e8373 100644
--- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
+++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
@@ -23,6 +23,7 @@
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
+import android.util.SparseArray;
import com.android.settings.Utils;
import com.android.settings.applications.UserManagerWrapper;
@@ -35,10 +36,12 @@
* SecondaryUserController controls the preferences on the Storage screen which had to do with
* secondary users.
*/
-public class SecondaryUserController extends PreferenceController {
+public class SecondaryUserController extends PreferenceController implements
+ StorageAsyncLoader.ResultHandler {
// PreferenceGroupKey to try to add our preference onto.
private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
private static final String PREFERENCE_KEY_BASE = "pref_user_";
+ private static final int USER_PROFILE_INSERTION_LOCATION = 6;
private static final int SIZE_NOT_SET = -1;
private @NonNull UserInfo mUser;
@@ -59,7 +62,13 @@
List<UserInfo> infos = userManager.getUsers();
for (int i = 0, size = infos.size(); i < size; i++) {
UserInfo info = infos.get(i);
+ if (info.equals(primaryUser)) {
+ continue;
+ }
+
if (info == null || Utils.isProfileOf(primaryUser, info)) {
+ controllers.add(new UserProfileController(context, info,
+ USER_PROFILE_INSERTION_LOCATION));
continue;
}
@@ -131,6 +140,14 @@
}
}
+ public void handleResult(SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
+ int userId = getUser().id;
+ StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
+ if (result != null) {
+ setSize(result.externalStats.totalBytes);
+ }
+ }
+
private static class NoSecondaryUserController extends PreferenceController {
public NoSecondaryUserController(Context context) {
super(context);
diff --git a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
index a60831b..d5d96a5 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageAsyncLoader.java
@@ -23,10 +23,9 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.UserInfo;
import android.os.UserHandle;
-import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.SparseArray;
import android.util.Log;
+import android.util.SparseArray;
import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.applications.UserManagerWrapper;
@@ -34,7 +33,6 @@
import com.android.settingslib.applications.StorageStatsSource;
import java.util.List;
-import java.util.Map;
/**
* StorageAsyncLoader is a Loader which loads categorized app information and external stats for all
@@ -118,4 +116,12 @@
public long otherAppsSize;
public StorageStatsSource.ExternalStorageStats externalStats;
}
+
+ /**
+ * ResultHandler defines a destination of data which can handle a result from
+ * {@link StorageAsyncLoader}.
+ */
+ public interface ResultHandler {
+ void handleResult(SparseArray<AppsStorageResult> result);
+ }
}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 88ba152..e31d968 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -22,7 +22,6 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
-import android.os.UserManager;
import android.os.storage.VolumeInfo;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
@@ -36,12 +35,12 @@
import com.android.settings.applications.ManageApplications;
import com.android.settings.core.PreferenceController;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
-
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.deviceinfo.StorageMeasurement;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
-import com.android.settingslib.applications.StorageStatsSource;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
@@ -70,7 +69,7 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final StorageVolumeProvider mSvp;
private VolumeInfo mVolume;
- private final int mUserId;
+ private int mUserId;
private long mSystemSize;
private StorageItemPreferenceAlternate mPhotoPreference;
@@ -89,8 +88,7 @@
mVolume = volume;
mSvp = svp;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- UserManager um = mContext.getSystemService(UserManager.class);
- mUserId = um.getUserHandle();
+ mUserId = UserHandle.myUserId();
}
@Override
@@ -157,6 +155,13 @@
mVolume = volume;
}
+ /**
+ * Sets the user id for which this preference controller is handling.
+ */
+ public void setUserId(int userId) {
+ mUserId = userId;
+ }
+
@Override
public void displayPreference(PreferenceScreen screen) {
mPhotoPreference = (StorageItemPreferenceAlternate) screen.findPreference(PHOTO_KEY);
@@ -173,7 +178,9 @@
mAudioPreference.setStorageSize(data.musicAppsSize + data.externalStats.audioBytes);
mGamePreference.setStorageSize(data.gamesSize);
mAppPreference.setStorageSize(data.otherAppsSize);
- mSystemPreference.setStorageSize(mSystemSize);
+ if (mSystemPreference != null) {
+ mSystemPreference.setStorageSize(mSystemSize);
+ }
long unattributedBytes = data.externalStats.totalBytes - data.externalStats.audioBytes
- data.externalStats.videoBytes - data.externalStats.imageBytes;
@@ -188,6 +195,20 @@
mSystemSize = systemSize;
}
+ /**
+ * Returns a list of keys used by this preference controller.
+ */
+ public static List<String> getUsedKeys() {
+ List<String> list = new ArrayList<>();
+ list.add(PHOTO_KEY);
+ list.add(AUDIO_KEY);
+ list.add(GAME_KEY);
+ list.add(OTHER_APPS_KEY);
+ list.add(SYSTEM_KEY);
+ list.add(FILES_KEY);
+ return list;
+ }
+
private Intent getPhotosIntent() {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
diff --git a/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java b/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java
deleted file mode 100644
index 98038fd..0000000
--- a/src/com/android/settings/deviceinfo/storage/StorageStatsSource.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.settings.deviceinfo.storage;
-
-import android.app.usage.StorageStats;
-import android.app.usage.StorageStatsManager;
-import android.content.Context;
-import android.os.UserHandle;
-
-/**
- * StorageStatsSource wraps the StorageStatsManager for testability purposes.
- */
-public class StorageStatsSource {
- private StorageStatsManager mStorageStatsManager;
-
- public StorageStatsSource(Context context) {
- mStorageStatsManager = context.getSystemService(StorageStatsManager.class);
- }
-
- public ExternalStorageStats getExternalStorageStats(String volumeUuid, UserHandle user) {
- return new ExternalStorageStats(
- mStorageStatsManager.queryExternalStatsForUser(volumeUuid, user));
- }
-
- public AppStorageStats getStatsForUid(String volumeUuid, int uid) {
- return new AppStorageStatsImpl(mStorageStatsManager.queryStatsForUid(volumeUuid, uid));
- }
-
- public static class ExternalStorageStats {
- public long totalBytes;
- public long audioBytes;
- public long videoBytes;
- public long imageBytes;
-
- public ExternalStorageStats(long totalBytes, long audioBytes, long videoBytes,
- long imageBytes) {
- this.totalBytes = totalBytes;
- this.audioBytes = audioBytes;
- this.videoBytes = videoBytes;
- this.imageBytes = imageBytes;
- }
-
- public ExternalStorageStats(android.app.usage.ExternalStorageStats stats) {
- totalBytes = stats.getTotalBytes();
- audioBytes = stats.getAudioBytes();
- videoBytes = stats.getVideoBytes();
- imageBytes = stats.getImageBytes();
- }
- }
-
- public interface AppStorageStats {
- long getCodeBytes();
- long getDataBytes();
- long getCacheBytes();
- }
-
- public static class AppStorageStatsImpl implements AppStorageStats {
- private StorageStats mStats;
-
- public AppStorageStatsImpl(StorageStats stats) {
- mStats = stats;
- }
-
- public long getCodeBytes() {
- return mStats.getCodeBytes();
- }
-
- public long getDataBytes() {
- return mStats.getDataBytes();
- }
-
- public long getCacheBytes() {
- return mStats.getCacheBytes();
- }
- }
-}
diff --git a/src/com/android/settings/deviceinfo/storage/UserProfileController.java b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
new file mode 100644
index 0000000..5da9fec
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.storage;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.storage.VolumeInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.SparseArray;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.util.Preconditions;
+import com.android.settings.Utils;
+import com.android.settings.core.PreferenceController;
+import com.android.settings.deviceinfo.StorageProfileFragment;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
+
+/**
+ * Defines a {@link PreferenceController} which handles a single profile of the primary user.
+ */
+public class UserProfileController extends PreferenceController implements
+ StorageAsyncLoader.ResultHandler {
+ private static final String PREFERENCE_KEY_BASE = "pref_profile_";
+ private StorageItemPreferenceAlternate mStoragePreference;
+ private UserInfo mUser;
+ private final int mPreferenceOrder;
+
+ public UserProfileController(Context context, UserInfo info, int preferenceOrder) {
+ super(context);
+ mUser = Preconditions.checkNotNull(info);
+ mPreferenceOrder = preferenceOrder;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREFERENCE_KEY_BASE + mUser.id;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mStoragePreference = new StorageItemPreferenceAlternate(mContext);
+ mStoragePreference.setOrder(mPreferenceOrder);
+ mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
+ mStoragePreference.setTitle(mUser.name);
+ screen.addPreference(mStoragePreference);
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (preference != null && mStoragePreference == preference) {
+ Bundle args = new Bundle(2);
+ args.putInt(StorageProfileFragment.USER_ID_EXTRA, mUser.id);
+ args.putString(VolumeInfo.EXTRA_VOLUME_ID, VolumeInfo.ID_PRIVATE_INTERNAL);
+ Intent intent = Utils.onBuildStartFragmentIntent(mContext,
+ StorageProfileFragment.class.getName(), args, null, 0,
+ mUser.name, false, MetricsProto.MetricsEvent.DEVICEINFO_STORAGE);
+ intent.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true);
+ mContext.startActivity(intent);
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void handleResult(SparseArray<StorageAsyncLoader.AppsStorageResult> stats) {
+ Preconditions.checkNotNull(stats);
+
+ int userId = mUser.id;
+ StorageAsyncLoader.AppsStorageResult result = stats.get(userId);
+ if (result != null) {
+ setSize(result.externalStats.totalBytes);
+ }
+ }
+
+ /**
+ * Sets the size for the preference using a byte count.
+ */
+ public void setSize(long size) {
+ if (mStoragePreference != null) {
+ mStoragePreference.setStorageSize(size);
+ }
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index 3d27d22..0236a30 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -101,27 +101,6 @@
}
}
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- MenuItem refresh = menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
- .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
- .setAlphabeticShortcut('r');
- refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM |
- MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- }
-
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case MENU_STATS_REFRESH:
- mStatsHelper.clearStats();
- refreshStats();
- mHandler.removeMessages(MSG_REFRESH_STATS);
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
protected void refreshStats() {
mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, mUm.getUserProfiles());
}
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 07e1459..956ac0b 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -45,6 +45,7 @@
import com.android.settings.datausage.DataUsageMeteredSettings;
import com.android.settings.datausage.DataUsageSummary;
import com.android.settings.deviceinfo.StorageDashboardFragment;
+import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.display.ScreenZoomSettings;
import com.android.settings.enterprise.EnterprisePrivacySettings;
diff --git a/src/com/android/settings/search2/DatabaseResultLoader.java b/src/com/android/settings/search2/DatabaseResultLoader.java
index b7f5dd7..ad1e6a9 100644
--- a/src/com/android/settings/search2/DatabaseResultLoader.java
+++ b/src/com/android/settings/search2/DatabaseResultLoader.java
@@ -144,7 +144,7 @@
results.addAll(secondaryResults);
results.addAll(tertiaryResults);
- return results;
+ return removeDuplicates(results);
}
@Override
@@ -300,4 +300,55 @@
}
return selection;
}
+
+ /**
+ * Goes through the list of search results and verifies that none of the results are duplicates.
+ * A duplicate is quantified by a result with the same Title and the same non-empty Summary.
+ *
+ * The method walks through the results starting with the highest priority result. It removes
+ * the duplicates by doing the first rule that applies below:
+ * - If a result is inline, remove the intent result.
+ * - Remove the lower rank item.
+ * @param results A list of results with potential duplicates
+ * @return The list of results with duplicates removed.
+ */
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ List<SearchResult> removeDuplicates(List<SearchResult> results) {
+ SearchResult primaryResult, secondaryResult;
+
+ // We accept the O(n^2) solution because the number of results is small.
+ for (int i = results.size() - 1; i >= 0; i--) {
+ secondaryResult = results.get(i);
+
+ for (int j = i - 1; j >= 0; j--) {
+ primaryResult = results.get(j);
+ if (areDuplicateResults(primaryResult, secondaryResult)) {
+
+ if (primaryResult.viewType != ResultPayload.PayloadType.INTENT) {
+ // Case where both payloads are inline
+ results.remove(i);
+ break;
+ } else if (secondaryResult.viewType != ResultPayload.PayloadType.INTENT) {
+ // Case where only second result is inline
+ results.remove(j);
+ i--; // shift the top index to reflect the lower element being removed
+ } else {
+ // Case where both payloads are intent
+ results.remove(i);
+ }
+ }
+ }
+ }
+ return results;
+ }
+
+ /**
+ * @return True when the two {@link SearchResult SearchResults} have the same title, and the same
+ * non-empty summary.
+ */
+ private boolean areDuplicateResults(SearchResult primary, SearchResult secondary) {
+ return TextUtils.equals(primary.title, secondary.title)
+ && TextUtils.equals(primary.summary, secondary.summary)
+ && !TextUtils.isEmpty(primary.summary);
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index a903c09..d97b461 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -194,7 +194,6 @@
mConnectedAccessPointPreferenceCategory =
(PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
- mConnectedAccessPointPreferenceCategory.setVisible(false); // initially hidden
mAccessPointsPreferenceCategory =
(PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
@@ -799,6 +798,7 @@
if (pref == null) {
pref = createLongPressActionPointPreference(connectedAp);
}
+ pref.refresh();
mConnectedAccessPointPreferenceCategory.addPreference(pref);
mConnectedAccessPointPreferenceCategory.setVisible(true);
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 5e134bf..76d1013 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -4,4 +4,5 @@
com.android.settings.inputmethod.InputAndGestureSettings
com.android.settings.accounts.AccountDetailDashboardFragment
com.android.settings.gestures.GestureSettings
-com.android.settings.fuelgauge.PowerUsageDetail
\ No newline at end of file
+com.android.settings.fuelgauge.PowerUsageDetail
+com.android.settings.deviceinfo.StorageProfileFragment
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 90a6e05..324e751 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -1,13 +1,25 @@
package com.android.settings;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.storage.DiskInfo;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.text.format.DateUtils;
-import java.net.InetAddress;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -16,9 +28,7 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
+import java.net.InetAddress;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -97,4 +107,13 @@
assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime);
}
+
+ @Test
+ public void testInitializeVolumeDoesntBreakOnNullVolume() {
+ VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
+ StorageManager storageManager = mock(StorageManager.class, RETURNS_DEEP_STUBS);
+ when(storageManager.findVolumeById(anyString())).thenReturn(info);
+
+ Utils.maybeInitializeVolume(storageManager, new Bundle());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
index 4af0707..592293d 100644
--- a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
@@ -32,8 +32,8 @@
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
-import com.android.settings.deviceinfo.storage.StorageStatsSource;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
+import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
index 10cfba0..644a942 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
@@ -36,7 +36,9 @@
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
@@ -68,7 +70,18 @@
}
@Test
- public void isAlwaysAvailable() {
+ public void isAvailable_noBrowser_shouldReturnFalse() {
+ when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+ .thenReturn(null);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_hasBrowser_shouldReturnTrue() {
+ final List<ResolveInfo> candidates = new ArrayList<>();
+ candidates.add(new ResolveInfo());
+ when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+ .thenReturn(candidates);
assertThat(mController.isAvailable()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
index f16304e..e2a46de 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
@@ -79,11 +79,4 @@
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
}
-
- @Test
- public void testInitializeVolumeDoesntBreakOnNullVolume() {
- VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
- when(mStorageManager.findVolumeById(anyString())).thenReturn(info);
- mFragment.initializeVolume(mStorageManager, new Bundle());
- }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
index b11132d..7222f53 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
@@ -28,11 +28,13 @@
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
+import android.util.SparseArray;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.core.PreferenceController;
+import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
@@ -130,7 +132,7 @@
}
@Test
- public void profilesOfPrimaryUserAreIgnored() throws Exception {
+ public void profilesOfPrimaryUserAreNotIgnored() throws Exception {
ArrayList<UserInfo> userInfos = new ArrayList<>();
UserInfo secondaryUser = new UserInfo();
secondaryUser.id = mPrimaryUser.id;
@@ -142,7 +144,31 @@
List<PreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
- assertThat(controllers).hasSize(1);
- assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
+ assertThat(controllers).hasSize(2);
+ assertThat(controllers.get(0) instanceof UserProfileController).isTrue();
+ assertThat(controllers.get(1) instanceof SecondaryUserController).isFalse();
+ }
+
+ @Test
+ public void controllerUpdatesPreferenceOnAcceptingResult() throws Exception {
+ mPrimaryUser.name = TEST_NAME;
+ mPrimaryUser.id = 10;
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ PreferenceGroup group = mock(PreferenceGroup.class);
+ when(screen.findPreference(anyString())).thenReturn(group);
+ when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
+ mController.displayPreference(screen);
+ StorageAsyncLoader.AppsStorageResult userResult =
+ new StorageAsyncLoader.AppsStorageResult();
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
+ userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
+ result.put(10, userResult);
+
+ mController.handleResult(result);
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(group).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+
+ assertThat(preference.getSummary()).isEqualTo("99.00B");
}
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
new file mode 100644
index 0000000..2cd4f76
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.deviceinfo.storage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.util.SparseArray;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.SubSettings;
+import com.android.settings.TestConfig;
+import com.android.settings.applications.UserManagerWrapper;
+import com.android.settings.deviceinfo.StorageProfileFragment;
+import com.android.settingslib.applications.StorageStatsSource;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class UserProfileControllerTest {
+ private static final String TEST_NAME = "Fred";
+
+ @Mock
+ private UserManagerWrapper mUserManager;
+
+ private Context mContext;
+ private UserProfileController mController;
+ private UserInfo mPrimaryProfile;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mPrimaryProfile = new UserInfo();
+ mController = new UserProfileController(mContext, mPrimaryProfile, 0);
+ }
+
+ @Test
+ public void controllerAddsPrimaryProfilePreference() throws Exception {
+ mPrimaryProfile.name = TEST_NAME;
+ mPrimaryProfile.id = 10;
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ mController.displayPreference(screen);
+
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(screen).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+
+ assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
+ assertThat(preference.getKey()).isEqualTo("pref_profile_10");
+ }
+
+ @Test
+ public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
+ mPrimaryProfile.name = TEST_NAME;
+ mPrimaryProfile.id = 10;
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ mController.displayPreference(screen);
+
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(screen).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+ assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
+ final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(intentCaptor.capture());
+
+ Intent intent = intentCaptor.getValue();
+ assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
+ assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
+ StorageProfileFragment.class.getName());
+ }
+
+ @Test
+ public void acceptingResultUpdatesPreferenceSize() throws Exception {
+ mPrimaryProfile.name = TEST_NAME;
+ mPrimaryProfile.id = 10;
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ mController.displayPreference(screen);
+ SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
+ StorageAsyncLoader.AppsStorageResult userResult =
+ new StorageAsyncLoader.AppsStorageResult();
+ userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
+ result.put(10, userResult);
+
+ mController.handleResult(result);
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(screen).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+
+ assertThat(preference.getSummary()).isEqualTo("99.00B");
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 72f6a87..dab39e4 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -88,8 +88,6 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Menu mMenu;
@Mock
- private MenuItem mRefreshMenu;
- @Mock
private MenuItem mAdditionalBatteryInfoMenu;
@Mock
private MenuItem mToggleAppsMenu;
@@ -142,11 +140,6 @@
mFragment = new TestFragment(mContext);
- when(mMenu.add(Menu.NONE, MENU_STATS_REFRESH, Menu.NONE,
- R.string.menu_stats_refresh)
- .setIcon(com.android.internal.R.drawable.ic_menu_refresh)
- .setAlphabeticShortcut('r'))
- .thenReturn(mRefreshMenu);
when(mAdditionalBatteryInfoMenu.getItemId())
.thenReturn(MENU_ADDITIONAL_BATTERY_INFO);
when(mToggleAppsMenu.getItemId()).thenReturn(MENU_TOGGLE_APPS);
diff --git a/tests/robotests/src/com/android/settings/search2/DatabaseResultLoaderTest.java b/tests/robotests/src/com/android/settings/search2/DatabaseResultLoaderTest.java
index 3a21bb2..72c658f 100644
--- a/tests/robotests/src/com/android/settings/search2/DatabaseResultLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/search2/DatabaseResultLoaderTest.java
@@ -19,6 +19,7 @@
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import com.android.settings.SettingsRobolectricTestRunner;
@@ -38,6 +39,7 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.ArrayList;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
@@ -58,6 +60,15 @@
private Context mContext;
private DatabaseResultLoader loader;
+ private final String titleOne = "titleOne";
+ private final String titleTwo = "titleTwo";
+ private final String titleThree = "titleThree";
+ private final String titleFour = "titleFour";
+ private final String summaryOne = "summaryOne";
+ private final String summaryTwo = "summaryTwo";
+ private final String summaryThree = "summaryThree";
+ private final String summaryFour = "summaryFour";
+
SQLiteDatabase mDb;
@Before
@@ -104,49 +115,49 @@
}
@Test
- public void testSpecialCaseWord_MatchesNonPrefix() {
+ public void testSpecialCaseWord_matchesNonPrefix() {
insertSpecialCase("Data usage");
loader = new DatabaseResultLoader(mContext, "usage", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseSpace_Matches() {
+ public void testSpecialCaseSpace_matches() {
insertSpecialCase("space");
loader = new DatabaseResultLoader(mContext, " space ", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseDash_MatchesWordNoDash() {
+ public void testSpecialCaseDash_matchesWordNoDash() {
insertSpecialCase("wi-fi calling");
loader = new DatabaseResultLoader(mContext, "wifi", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseDash_MatchesWordWithDash() {
+ public void testSpecialCaseDash_matchesWordWithDash() {
insertSpecialCase("priorités seulment");
loader = new DatabaseResultLoader(mContext, "priorités", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseDash_MatchesWordWithoutDash() {
+ public void testSpecialCaseDash_matchesWordWithoutDash() {
insertSpecialCase("priorités seulment");
loader = new DatabaseResultLoader(mContext, "priorites", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseDash_MatchesEntireQueryWithoutDash() {
+ public void testSpecialCaseDash_matchesEntireQueryWithoutDash() {
insertSpecialCase("wi-fi calling");
loader = new DatabaseResultLoader(mContext, "wifi calling", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCasePrefix_MatchesPrefixOfEntry() {
+ public void testSpecialCasePrefix_matchesPrefixOfEntry() {
insertSpecialCase("Photos");
loader = new DatabaseResultLoader(mContext, "pho", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
@@ -160,14 +171,14 @@
}
@Test
- public void testSpecialCaseMultiWordPrefix_MatchesPrefixOfEntry() {
+ public void testSpecialCaseMultiWordPrefix_matchesPrefixOfEntry() {
insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "Apps", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseMultiWordPrefix_MatchesSecondWordPrefixOfEntry() {
+ public void testSpecialCaseMultiWordPrefix_matchesSecondWordPrefixOfEntry() {
insertSpecialCase("Apps Notifications");
loader = new DatabaseResultLoader(mContext, "Not", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
@@ -188,21 +199,188 @@
}
@Test
- public void testSpecialCaseMultiWordPrefixWithSpecial_MatchesPrefixOfEntry() {
+ public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfEntry() {
insertSpecialCase("Apps & Notifications");
loader = new DatabaseResultLoader(mContext, "App", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseMultiWordPrefixWithSpecial_MatchesPrefixOfSecondEntry() {
+ public void testSpecialCaseMultiWordPrefixWithSpecial_matchesPrefixOfSecondEntry() {
insertSpecialCase("Apps & Notifications");
loader = new DatabaseResultLoader(mContext, "No", mSiteMapManager);
assertThat(loader.loadInBackground().size()).isEqualTo(1);
}
@Test
- public void testSpecialCaseTwoWords_FirstWordMatches_RanksHigher() {
+ public void testDeDupe_noDuplicates_originalListReturn() {
+ // Three elements with unique titles and summaries
+ List<SearchResult> results = new ArrayList();
+ IntentPayload intentPayload = new IntentPayload(new Intent());
+
+ SearchResult.Builder builder = new SearchResult.Builder();
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addPayload(intentPayload);
+ SearchResult resultOne = builder.build();
+ results.add(resultOne);
+
+ builder.addTitle(titleTwo)
+ .addSummary(summaryTwo);
+ SearchResult resultTwo = builder.build();
+ results.add(resultTwo);
+
+ builder.addTitle(titleThree)
+ .addSummary(summaryThree);
+ SearchResult resultThree = builder.build();
+ results.add(resultThree);
+
+ loader = new DatabaseResultLoader(mContext, "", null);
+ loader.removeDuplicates(results);
+ assertThat(results.size()).isEqualTo(3);
+ assertThat(results.get(0)).isEqualTo(resultOne);
+ assertThat(results.get(1)).isEqualTo(resultTwo);
+ assertThat(results.get(2)).isEqualTo(resultThree);
+ }
+
+ @Test
+ public void testDeDupe_oneDuplicate_duplicateRemoved() {
+ List<SearchResult> results = new ArrayList();
+ IntentPayload intentPayload = new IntentPayload(new Intent());
+
+ SearchResult.Builder builder = new SearchResult.Builder();
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addRank(0)
+ .addPayload(intentPayload);
+ SearchResult resultOne = builder.build();
+ results.add(resultOne);
+
+ // Duplicate of the first element
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addRank(1);
+ SearchResult resultTwo = builder.build();
+ results.add(resultTwo);
+
+ // Unique
+ builder.addTitle(titleThree)
+ .addSummary(summaryThree);
+ SearchResult resultThree = builder.build();
+ results.add(resultThree);
+
+ loader = new DatabaseResultLoader(mContext, "", null);
+ loader.removeDuplicates(results);
+ assertThat(results.size()).isEqualTo(2);
+ assertThat(results.get(0)).isEqualTo(resultOne);
+ assertThat(results.get(1)).isEqualTo(resultThree);
+ }
+
+ @Test
+ public void testDeDupe_firstDupeInline_secondDuplicateRemoved() {
+ List<SearchResult> results = new ArrayList();
+ InlineSwitchPayload inlinePayload = new InlineSwitchPayload("", 0,
+ null);
+ IntentPayload intentPayload = new IntentPayload(new Intent());
+
+ SearchResult.Builder builder = new SearchResult.Builder();
+ // Inline result
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addRank(0)
+ .addPayload(inlinePayload);
+ SearchResult resultOne = builder.build();
+ results.add(resultOne);
+
+ // Duplicate of first result, but Intent Result. Should be removed.
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addRank(1)
+ .addPayload(intentPayload);
+ SearchResult resultTwo = builder.build();
+ results.add(resultTwo);
+
+ // Unique
+ builder.addTitle(titleThree)
+ .addSummary(summaryThree);
+ SearchResult resultThree = builder.build();
+ results.add(resultThree);
+
+ loader = new DatabaseResultLoader(mContext, "", null);
+ loader.removeDuplicates(results);
+ assertThat(results.size()).isEqualTo(2);
+ assertThat(results.get(0)).isEqualTo(resultOne);
+ assertThat(results.get(1)).isEqualTo(resultThree);
+ }
+
+ @Test
+ public void testDeDupe_secondDupeInline_firstDuplicateRemoved() {
+ /*
+ * Create a list as follows:
+ * (5) Intent Four
+ * (4) Inline Two
+ * (3) Intent Three
+ * (2) Intent Two
+ * (1) Intent One
+ *
+ * After removing duplicates:
+ * (4) Intent Four
+ * (3) Inline Two
+ * (2) Intent Three
+ * (1) Intent One
+ */
+ List<SearchResult> results = new ArrayList();
+ InlineSwitchPayload inlinePayload = new InlineSwitchPayload("", 0,
+ null);
+ IntentPayload intentPayload = new IntentPayload(new Intent());
+
+
+ SearchResult.Builder builder = new SearchResult.Builder();
+ // Intent One
+ builder.addTitle(titleOne)
+ .addSummary(summaryOne)
+ .addPayload(intentPayload);
+ SearchResult resultOne = builder.build();
+ results.add(resultOne);
+
+ // Intent Two
+ builder.addTitle(titleTwo)
+ .addSummary(summaryTwo)
+ .addPayload(intentPayload);
+ SearchResult resultTwo = builder.build();
+ results.add(resultTwo);
+
+ // Intent Three
+ builder.addTitle(titleThree)
+ .addSummary(summaryThree);
+ SearchResult resultThree = builder.build();
+ results.add(resultThree);
+
+ // Inline Two
+ builder.addTitle(titleTwo)
+ .addSummary(summaryTwo)
+ .addPayload(inlinePayload);
+ SearchResult resultFour = builder.build();
+ results.add(resultFour);
+
+ // Intent Four
+ builder.addTitle(titleFour)
+ .addSummary(summaryOne)
+ .addPayload(intentPayload);
+ SearchResult resultFive = builder.build();
+ results.add(resultFive);
+
+ loader = new DatabaseResultLoader(mContext, "", null);
+ loader.removeDuplicates(results);
+ assertThat(results.size()).isEqualTo(4);
+ assertThat(results.get(0)).isEqualTo(resultOne);
+ assertThat(results.get(1)).isEqualTo(resultThree);
+ assertThat(results.get(2)).isEqualTo(resultFour);
+ assertThat(results.get(3)).isEqualTo(resultFive);
+ }
+
+ @Test
+ public void testSpecialCaseTwoWords_firstWordMatches_ranksHigher() {
final String caseOne = "Apple pear";
final String caseTwo = "Banana apple";
insertSpecialCase(caseOne);
diff --git a/tests/unit/src/com/android/settings/TetherServiceTest.java b/tests/unit/src/com/android/settings/TetherServiceTest.java
index bec3e7e..899ea7a 100644
--- a/tests/unit/src/com/android/settings/TetherServiceTest.java
+++ b/tests/unit/src/com/android/settings/TetherServiceTest.java
@@ -415,6 +415,7 @@
private void sendResponse(int response, Context context) {
Intent responseIntent = new Intent(TEST_RESPONSE_ACTION);
+ responseIntent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
responseIntent.putExtra(TetherService.EXTRA_RESULT, response);
context.sendBroadcast(
responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);