mSuggestionsShownLogged.add(suggestionId);
}
if (suggestion.remoteViews != null) {
+ TileUtils.updateTileUsingSummaryUri(mContext, suggestion);
final ViewGroup itemView = (ViewGroup) holder.itemView;
itemView.removeAllViews();
itemView.addView(suggestion.remoteViews.apply(itemView.getContext(), itemView));
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java
new file mode 100644
index 00000000000..261f66cea6e
--- /dev/null
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceController.java
@@ -0,0 +1,76 @@
+/**
+ * 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.deletionhelper;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.format.DateUtils;
+import android.text.format.Formatter;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+/**
+ * Handles the wall of text which appears below the options in the Storage Management settings drill
+ * down.
+ */
+public class AutomaticStorageManagerDescriptionPreferenceController
+ extends AbstractPreferenceController implements PreferenceControllerMixin {
+ private static final String KEY_FREED = "freed_bytes";
+
+ public AutomaticStorageManagerDescriptionPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_FREED;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ Preference preference = screen.findPreference(getPreferenceKey());
+ final Context context = preference.getContext();
+ ContentResolver cr = context.getContentResolver();
+ long freedBytes =
+ Settings.Secure.getLong(
+ cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED, 0);
+ long lastRunMillis =
+ Settings.Secure.getLong(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN, 0);
+ if (freedBytes == 0 || lastRunMillis == 0 || !isStorageManagerEnabled(cr)) {
+ preference.setSummary(R.string.automatic_storage_manager_text);
+ } else {
+ preference.setSummary(
+ context.getString(
+ R.string.automatic_storage_manager_freed_bytes,
+ Formatter.formatFileSize(context, freedBytes),
+ DateUtils.formatDateTime(
+ context, lastRunMillis, DateUtils.FORMAT_SHOW_DATE)));
+ }
+ }
+
+ private boolean isStorageManagerEnabled(ContentResolver cr) {
+ return Settings.Secure.getInt(cr, Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0)
+ != 0;
+ }
+}
diff --git a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
index f7b62b1666f..e38317a824d 100644
--- a/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
+++ b/src/com/android/settings/deletionhelper/AutomaticStorageManagerSettings.java
@@ -16,15 +16,13 @@
package com.android.settings.deletionhelper;
-import android.app.Activity;
import android.content.ContentResolver;
+import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.text.format.DateUtils;
-import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -32,39 +30,34 @@ import android.view.ViewGroup;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
-import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* AutomaticStorageManagerSettings is the Settings screen for configuration and management of the
* automatic storage manager.
*/
-public class AutomaticStorageManagerSettings extends SettingsPreferenceFragment
+public class AutomaticStorageManagerSettings extends DashboardFragment
implements OnPreferenceChangeListener {
private static final String KEY_DAYS = "days";
- private static final String KEY_FREED = "freed_bytes";
- private static final String STORAGE_MANAGER_ENABLED_BY_DEFAULT_PROPERTY =
- "ro.storage_manager.enabled";
private AutomaticStorageManagerSwitchBarController mSwitchController;
private DropDownPreference mDaysToRetain;
- private Preference mFreedBytes;
private SwitchBar mSwitchBar;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.automatic_storage_management_settings);
- }
-
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
initializeDaysToRetainPreference();
- initializeFreedBytesPreference();
initializeSwitchBar();
return view;
@@ -98,35 +91,25 @@ public class AutomaticStorageManagerSettings extends SettingsPreferenceFragment
getFragmentManager());
}
- private void initializeFreedBytesPreference() {
- ContentResolver cr = getContentResolver();
- mFreedBytes = findPreference(KEY_FREED);
- long freedBytes = Settings.Secure.getLong(cr,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
- 0);
- long lastRunMillis = Settings.Secure.getLong(cr,
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
- 0);
- if (freedBytes == 0 || lastRunMillis == 0) {
- mFreedBytes.setVisible(false);
- } else {
- final Activity activity = getActivity();
- mFreedBytes.setSummary(
- activity.getString(
- R.string.automatic_storage_manager_freed_bytes,
- Formatter.formatFileSize(activity, freedBytes),
- DateUtils.formatDateTime(
- activity, lastRunMillis, DateUtils.FORMAT_SHOW_DATE)));
- }
- }
-
@Override
public void onResume() {
super.onResume();
- boolean isStorageManagerChecked =
- Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0) != 0;
- mDaysToRetain.setEnabled(isStorageManagerChecked);
+ mDaysToRetain.setEnabled(isStorageManagerEnabled());
+ }
+
+ @Override
+ protected String getLogTag() {
+ return null;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.automatic_storage_management_settings;
+ }
+
+ @Override
+ protected List getPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context);
}
@Override
@@ -168,4 +151,30 @@ public class AutomaticStorageManagerSettings extends SettingsPreferenceFragment
return indices.length - 1;
}
+ private boolean isStorageManagerEnabled() {
+ return Settings.Secure.getInt(
+ getContentResolver(), Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED, 0)
+ != 0;
+ }
+
+ private static List buildPreferenceControllers(Context context) {
+ final List controllers = new ArrayList<>();
+ controllers.add(new AutomaticStorageManagerDescriptionPreferenceController(context));
+ return controllers;
+ }
+
+ /** For Search. */
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return false;
+ }
+
+ @Override
+ public List getPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context);
+ }
+ };
}
diff --git a/src/com/android/settings/development/DevelopmentSettings.java b/src/com/android/settings/development/DevelopmentSettings.java
index 3ee1295e802..3759ea1b9e2 100644
--- a/src/com/android/settings/development/DevelopmentSettings.java
+++ b/src/com/android/settings/development/DevelopmentSettings.java
@@ -53,6 +53,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
import android.provider.SearchIndexableResource;
@@ -1029,8 +1030,19 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
return context.getSystemService(Context.OEM_LOCK_SERVICE) != null;
}
+ /**
+ * Returns whether OEM unlock is allowed by the user and carrier.
+ *
+ * This does not take into account any restrictions imposed by the device policy.
+ */
+ private boolean isOemUnlockAllowedByUserAndCarrier() {
+ final UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
+ return mOemLockManager.isOemUnlockAllowedByCarrier()
+ && !mUm.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, userHandle);
+ }
+
private boolean enableOemUnlockPreference() {
- return !isBootloaderUnlocked() && mOemLockManager.canUserAllowOemUnlock();
+ return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier();
}
private void updateOemUnlockOptions() {
@@ -1044,10 +1056,6 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
// Check restriction, disable mEnableOemUnlock and apply policy transparency.
mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
}
- if (mEnableOemUnlock.isEnabled()) {
- // Check restriction, disable mEnableOemUnlock and apply policy transparency.
- mEnableOemUnlock.checkRestrictionAndSetDisabled(UserManager.DISALLOW_OEM_UNLOCK);
- }
}
}
@@ -2572,7 +2580,7 @@ public class DevelopmentSettings extends RestrictedSettingsFragment
oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked;
} else if (isSimLockedDevice()) {
oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device;
- } else if (!mOemLockManager.canUserAllowOemUnlock()) {
+ } else if (!isOemUnlockAllowedByUserAndCarrier()) {
// If the device isn't SIM-locked but OEM unlock is disallowed by some party, this
// means either some other carrier restriction is in place or the device hasn't been
// able to confirm which restrictions (SIM-lock or otherwise) apply.
diff --git a/src/com/android/settings/deviceinfo/Status.java b/src/com/android/settings/deviceinfo/Status.java
index baddc6cac2b..faa4134a935 100644
--- a/src/com/android/settings/deviceinfo/Status.java
+++ b/src/com/android/settings/deviceinfo/Status.java
@@ -28,11 +28,15 @@ import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -56,6 +60,7 @@ public class Status extends SettingsPreferenceFragment {
private static final String KEY_WIMAX_MAC_ADDRESS = "wimax_mac_address";
private static final String KEY_SIM_STATUS = "sim_status";
private static final String KEY_IMEI_INFO = "imei_info";
+ private static final String KEY_IMS_REGISTRATION_STATE = "ims_reg_state";
// Broadcasts to listen to for connectivity changes.
private static final String[] CONNECTIVITY_INTENTS = {
@@ -85,6 +90,8 @@ public class Status extends SettingsPreferenceFragment {
private Preference mIpAddress;
private Preference mWifiMacAddress;
private Preference mWimaxMacAddress;
+ private Preference mImsStatus;
+
private Handler mHandler;
private static class MyHandler extends Handler {
@@ -162,6 +169,7 @@ public class Status extends SettingsPreferenceFragment {
mWifiMacAddress = findPreference(KEY_WIFI_MAC_ADDRESS);
mWimaxMacAddress = findPreference(KEY_WIMAX_MAC_ADDRESS);
mIpAddress = findPreference(KEY_IP_ADDRESS);
+ mImsStatus = findPreference(KEY_IMS_REGISTRATION_STATE);
mRes = getResources();
mUnavailable = mRes.getString(R.string.status_unavailable);
@@ -269,11 +277,31 @@ public class Status extends SettingsPreferenceFragment {
}
}
+ private void setImsRegistrationStatus() {
+ CarrierConfigManager configManager = (CarrierConfigManager)
+ getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+ PersistableBundle config = null;
+ if (configManager != null) {
+ config = configManager.getConfigForSubId(subId);
+ }
+ if (config != null && config.getBoolean(
+ CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL)) {
+ TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ mImsStatus.setSummary((tm != null && tm.isImsRegistered(subId)) ?
+ R.string.ims_reg_status_registered : R.string.ims_reg_status_not_registered);
+ } else {
+ removePreferenceFromScreen(KEY_IMS_REGISTRATION_STATE);
+ mImsStatus = null;
+ }
+ }
+
void updateConnectivity() {
setWimaxStatus();
setWifiStatus();
setBtStatus();
setIpAddressStatus();
+ setImsRegistrationStatus();
}
void updateTimes() {
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 33d7d36b85c..dd0db9a2335 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -40,6 +40,7 @@ import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.applications.UserManagerWrapperImpl;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.deviceinfo.storage.AutomaticStorageManagementSwitchPreferenceController;
+import com.android.settings.deviceinfo.storage.CachedStorageValuesHelper;
import com.android.settings.deviceinfo.storage.SecondaryUserController;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
@@ -68,6 +69,7 @@ public class StorageDashboardFragment extends DashboardFragment
private VolumeInfo mVolume;
private PrivateStorageInfo mStorageInfo;
private SparseArray mAppsResult;
+ private CachedStorageValuesHelper mCachedStorageValuesHelper;
private StorageSummaryDonutPreferenceController mSummaryController;
private StorageItemPreferenceController mPreferenceController;
@@ -102,7 +104,10 @@ public class StorageDashboardFragment extends DashboardFragment
@Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
- setLoading(true, false);
+ initializeCacheProvider();
+ if (mAppsResult == null || mStorageInfo == null) {
+ setLoading(true, false);
+ }
}
@Override
@@ -249,6 +254,7 @@ public class StorageDashboardFragment extends DashboardFragment
public void onLoadFinished(Loader> loader,
SparseArray data) {
mAppsResult = data;
+ maybeCacheFreshValues();
onReceivedSizes();
}
@@ -256,6 +262,48 @@ public class StorageDashboardFragment extends DashboardFragment
public void onLoaderReset(Loader> loader) {
}
+ @VisibleForTesting
+ public void setCachedStorageValuesHelper(CachedStorageValuesHelper helper) {
+ mCachedStorageValuesHelper = helper;
+ }
+
+ @VisibleForTesting
+ public PrivateStorageInfo getPrivateStorageInfo() {
+ return mStorageInfo;
+ }
+
+ @VisibleForTesting
+ public SparseArray getAppsStorageResult() {
+ return mAppsResult;
+ }
+
+ @VisibleForTesting
+ public void initializeCachedValues() {
+ PrivateStorageInfo info = mCachedStorageValuesHelper.getCachedPrivateStorageInfo();
+ SparseArray loaderResult =
+ mCachedStorageValuesHelper.getCachedAppsStorageResult();
+ if (info == null || loaderResult == null) {
+ return;
+ }
+
+ mStorageInfo = info;
+ mAppsResult = loaderResult;
+ }
+
+ private void initializeCacheProvider() {
+ mCachedStorageValuesHelper =
+ new CachedStorageValuesHelper(getContext(), UserHandle.myUserId());
+ initializeCachedValues();
+ onReceivedSizes();
+ }
+
+ private void maybeCacheFreshValues() {
+ if (mStorageInfo != null && mAppsResult != null) {
+ mCachedStorageValuesHelper.cacheResult(
+ mStorageInfo, mAppsResult.get(UserHandle.myUserId()));
+ }
+ }
+
/**
* IconLoaderCallbacks exists because StorageDashboardFragment already implements
* LoaderCallbacks for a different type.
@@ -308,6 +356,7 @@ public class StorageDashboardFragment extends DashboardFragment
}
mStorageInfo = privateStorageInfo;
+ maybeCacheFreshValues();
onReceivedSizes();
}
}
diff --git a/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java b/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java
new file mode 100644
index 00000000000..8225db39434
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelper.java
@@ -0,0 +1,172 @@
+/*
+ * 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.SharedPreferences;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.util.SparseArray;
+
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+
+import java.util.concurrent.TimeUnit;
+
+public class CachedStorageValuesHelper {
+
+ @VisibleForTesting public static final String SHARED_PREFERENCES_NAME = "CachedStorageValues";
+ public static final String TIMESTAMP_KEY = "last_query_timestamp";
+ public static final String FREE_BYTES_KEY = "free_bytes";
+ public static final String TOTAL_BYTES_KEY = "total_bytes";
+ public static final String GAME_APPS_SIZE_KEY = "game_apps_size";
+ public static final String MUSIC_APPS_SIZE_KEY = "music_apps_size";
+ public static final String VIDEO_APPS_SIZE_KEY = "video_apps_size";
+ public static final String PHOTO_APPS_SIZE_KEY = "photo_apps_size";
+ public static final String OTHER_APPS_SIZE_KEY = "other_apps_size";
+ public static final String CACHE_APPS_SIZE_KEY = "cache_apps_size";
+ public static final String EXTERNAL_TOTAL_BYTES = "external_total_bytes";
+ public static final String EXTERNAL_AUDIO_BYTES = "external_audio_bytes";
+ public static final String EXTERNAL_VIDEO_BYTES = "external_video_bytes";
+ public static final String EXTERNAL_IMAGE_BYTES = "external_image_bytes";
+ public static final String EXTERNAL_APP_BYTES = "external_apps_bytes";
+ public static final String USER_ID_KEY = "user_id";
+ private final Long mClobberThreshold;
+ private final SharedPreferences mSharedPreferences;
+ private final int mUserId;
+ // This clock is used to provide the time. By default, it uses the system clock, but can be
+ // replaced for test purposes.
+ protected Clock mClock;
+
+ public CachedStorageValuesHelper(Context context, int userId) {
+ mSharedPreferences =
+ context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
+ mClock = new Clock();
+ mUserId = userId;
+ mClobberThreshold =
+ Settings.Global.getLong(
+ context.getContentResolver(),
+ Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
+ TimeUnit.MINUTES.toMillis(5));
+ }
+
+ public PrivateStorageInfo getCachedPrivateStorageInfo() {
+ if (!isDataValid()) {
+ return null;
+ }
+ final long freeBytes = mSharedPreferences.getLong(FREE_BYTES_KEY, -1);
+ final long totalBytes = mSharedPreferences.getLong(TOTAL_BYTES_KEY, -1);
+ if (freeBytes < 0 || totalBytes < 0) {
+ return null;
+ }
+
+ return new PrivateStorageInfo(freeBytes, totalBytes);
+ }
+
+ public SparseArray getCachedAppsStorageResult() {
+ if (!isDataValid()) {
+ return null;
+ }
+ final long gamesSize = mSharedPreferences.getLong(GAME_APPS_SIZE_KEY, -1);
+ final long musicAppsSize = mSharedPreferences.getLong(MUSIC_APPS_SIZE_KEY, -1);
+ final long videoAppsSize = mSharedPreferences.getLong(VIDEO_APPS_SIZE_KEY, -1);
+ final long photoAppSize = mSharedPreferences.getLong(PHOTO_APPS_SIZE_KEY, -1);
+ final long otherAppsSize = mSharedPreferences.getLong(OTHER_APPS_SIZE_KEY, -1);
+ final long cacheSize = mSharedPreferences.getLong(CACHE_APPS_SIZE_KEY, -1);
+ if (gamesSize < 0
+ || musicAppsSize < 0
+ || videoAppsSize < 0
+ || photoAppSize < 0
+ || otherAppsSize < 0
+ || cacheSize < 0) {
+ return null;
+ }
+
+ final long externalTotalBytes = mSharedPreferences.getLong(EXTERNAL_TOTAL_BYTES, -1);
+ final long externalAudioBytes = mSharedPreferences.getLong(EXTERNAL_AUDIO_BYTES, -1);
+ final long externalVideoBytes = mSharedPreferences.getLong(EXTERNAL_VIDEO_BYTES, -1);
+ final long externalImageBytes = mSharedPreferences.getLong(EXTERNAL_IMAGE_BYTES, -1);
+ final long externalAppBytes = mSharedPreferences.getLong(EXTERNAL_APP_BYTES, -1);
+ if (externalTotalBytes < 0
+ || externalAudioBytes < 0
+ || externalVideoBytes < 0
+ || externalImageBytes < 0
+ || externalAppBytes < 0) {
+ return null;
+ }
+
+ final StorageStatsSource.ExternalStorageStats externalStats =
+ new StorageStatsSource.ExternalStorageStats(
+ externalTotalBytes,
+ externalAudioBytes,
+ externalVideoBytes,
+ externalImageBytes,
+ externalAppBytes);
+ final StorageAsyncLoader.AppsStorageResult result =
+ new StorageAsyncLoader.AppsStorageResult();
+ result.gamesSize = gamesSize;
+ result.musicAppsSize = musicAppsSize;
+ result.videoAppsSize = videoAppsSize;
+ result.photosAppsSize = photoAppSize;
+ result.otherAppsSize = otherAppsSize;
+ result.cacheSize = cacheSize;
+ result.externalStats = externalStats;
+ final SparseArray resultArray = new SparseArray<>();
+ resultArray.append(mUserId, result);
+ return resultArray;
+ }
+
+ public void cacheResult(
+ PrivateStorageInfo storageInfo, StorageAsyncLoader.AppsStorageResult result) {
+ mSharedPreferences
+ .edit()
+ .putLong(FREE_BYTES_KEY, storageInfo.freeBytes)
+ .putLong(TOTAL_BYTES_KEY, storageInfo.totalBytes)
+ .putLong(GAME_APPS_SIZE_KEY, result.gamesSize)
+ .putLong(MUSIC_APPS_SIZE_KEY, result.musicAppsSize)
+ .putLong(VIDEO_APPS_SIZE_KEY, result.videoAppsSize)
+ .putLong(PHOTO_APPS_SIZE_KEY, result.photosAppsSize)
+ .putLong(OTHER_APPS_SIZE_KEY, result.otherAppsSize)
+ .putLong(CACHE_APPS_SIZE_KEY, result.cacheSize)
+ .putLong(EXTERNAL_TOTAL_BYTES, result.externalStats.totalBytes)
+ .putLong(EXTERNAL_AUDIO_BYTES, result.externalStats.audioBytes)
+ .putLong(EXTERNAL_VIDEO_BYTES, result.externalStats.videoBytes)
+ .putLong(EXTERNAL_IMAGE_BYTES, result.externalStats.imageBytes)
+ .putLong(EXTERNAL_APP_BYTES, result.externalStats.appBytes)
+ .putInt(USER_ID_KEY, mUserId)
+ .putLong(TIMESTAMP_KEY, mClock.getCurrentTime())
+ .apply();
+ }
+
+ private boolean isDataValid() {
+ final int cachedUserId = mSharedPreferences.getInt(USER_ID_KEY, -1);
+ if (cachedUserId != mUserId) {
+ return false;
+ }
+
+ final long lastQueryTime = mSharedPreferences.getLong(TIMESTAMP_KEY, Long.MAX_VALUE);
+ final long currentTime = mClock.getCurrentTime();
+ return currentTime - lastQueryTime < mClobberThreshold;
+ }
+
+ /** Clock provides the current time. */
+ static class Clock {
+ public long getCurrentTime() {
+ return System.currentTimeMillis();
+ }
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index ca85f69d0be..163f5b9dff4 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -208,23 +208,18 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
public void setUserId(UserHandle userHandle) {
mUserId = userHandle.getIdentifier();
- PackageManager pm = mContext.getPackageManager();
- badgePreference(pm, userHandle, mPhotoPreference);
- badgePreference(pm, userHandle, mMoviesPreference);
- badgePreference(pm, userHandle, mAudioPreference);
- badgePreference(pm, userHandle, mGamePreference);
- badgePreference(pm, userHandle, mAppPreference);
- badgePreference(pm, userHandle, mSystemPreference);
- badgePreference(pm, userHandle, mFilePreference);
+ tintPreference(mPhotoPreference);
+ tintPreference(mMoviesPreference);
+ tintPreference(mAudioPreference);
+ tintPreference(mGamePreference);
+ tintPreference(mAppPreference);
+ tintPreference(mSystemPreference);
+ tintPreference(mFilePreference);
}
- private void badgePreference(PackageManager pm, UserHandle userHandle, Preference preference) {
+ private void tintPreference(Preference preference) {
if (preference != null) {
- Drawable currentIcon = preference.getIcon();
- // Sigh... Applying the badge to the icon clobbers the tint on the base drawable.
- // For some reason, reapplying it here means the tint remains.
- currentIcon = applyTint(mContext, currentIcon);
- preference.setIcon(pm.getUserBadgedIcon(currentIcon, userHandle));
+ preference.setIcon(applyTint(mContext, preference.getIcon()));
}
}
diff --git a/src/com/android/settings/search/DatabaseIndexingManager.java b/src/com/android/settings/search/DatabaseIndexingManager.java
index 7f6f0129548..a0f47d16542 100644
--- a/src/com/android/settings/search/DatabaseIndexingManager.java
+++ b/src/com/android/settings/search/DatabaseIndexingManager.java
@@ -17,27 +17,6 @@
package com.android.settings.search;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_RANK;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
-import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
import static com.android.settings.search.DatabaseResultLoader.COLUMN_INDEX_ID;
import static com.android.settings.search.DatabaseResultLoader
.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE;
@@ -70,17 +49,14 @@ import static com.android.settings.search.IndexDatabaseHelper.IndexColumns.USER_
import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
-import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.SearchIndexableData;
@@ -89,7 +65,6 @@ import android.provider.SearchIndexablesContract;
import android.support.annotation.DrawableRes;
import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -98,13 +73,13 @@ import com.android.settings.SettingsActivity;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.search.indexing.IndexableDataCollector;
+import com.android.settings.search.indexing.PreIndexData;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -132,23 +107,14 @@ public class DatabaseIndexingManager {
private static final String NODE_NAME_CHECK_BOX_PREFERENCE = "CheckBoxPreference";
private static final String NODE_NAME_LIST_PREFERENCE = "ListPreference";
- private static final List EMPTY_LIST = Collections.emptyList();
-
- private final String mBaseAuthority;
-
@VisibleForTesting
final AtomicBoolean mIsIndexingComplete = new AtomicBoolean(false);
- @VisibleForTesting
- final UpdateData mDataToProcess = new UpdateData();
+ private IndexableDataCollector mCollector;
+
private Context mContext;
- public DatabaseIndexingManager(Context context, String baseAuthority) {
- mContext = context;
- mBaseAuthority = baseAuthority;
- }
-
- public void setContext(Context context) {
+ public DatabaseIndexingManager(Context context) {
mContext = context;
}
@@ -177,33 +143,17 @@ public class DatabaseIndexingManager {
final String providerVersionedNames =
IndexDatabaseHelper.buildProviderVersionedNames(providers);
- final boolean isFullIndex = IndexDatabaseHelper.isFullIndex(mContext, localeStr,
+ final boolean isFullIndex = isFullIndex(mContext, localeStr,
fingerprint, providerVersionedNames);
if (isFullIndex) {
rebuildDatabase();
}
- for (final ResolveInfo info : providers) {
- if (!DatabaseIndexingUtils.isWellKnownProvider(info, mContext)) {
- continue;
- }
- final String authority = info.providerInfo.authority;
- final String packageName = info.providerInfo.packageName;
+ PreIndexData indexData = getIndexDataFromProviders(providers, isFullIndex);
- if (isFullIndex) {
- addIndexablesFromRemoteProvider(packageName, authority);
- }
- final long nonIndexableStartTime = System.currentTimeMillis();
- addNonIndexablesKeysFromRemoteProvider(packageName, authority);
- if (SettingsSearchIndexablesProvider.DEBUG) {
- final long nonIndextableTime = System.currentTimeMillis() - nonIndexableStartTime;
- Log.d(LOG_TAG, "performIndexing update non-indexable for package " + packageName
- + " took time: " + nonIndextableTime);
- }
- }
final long updateDatabaseStartTime = System.currentTimeMillis();
- updateDatabase(isFullIndex, localeStr);
+ updateDatabase(indexData, isFullIndex, localeStr);
if (SettingsSearchIndexablesProvider.DEBUG) {
final long updateDatabaseTime = System.currentTimeMillis() - updateDatabaseStartTime;
Log.d(LOG_TAG, "performIndexing updateDatabase took time: " + updateDatabaseTime);
@@ -221,10 +171,37 @@ public class DatabaseIndexingManager {
}
}
+ @VisibleForTesting
+ PreIndexData getIndexDataFromProviders(List providers, boolean isFullIndex) {
+ if (mCollector == null) {
+ mCollector = new IndexableDataCollector(mContext);
+ }
+ return mCollector.collectIndexableData(providers, isFullIndex);
+ }
+
/**
- * Reconstruct the database in the following cases:
- * - Language has changed
- * - Build has changed
+ * Checks if the indexed data is obsolete, when either:
+ * - Device language has changed
+ * - Device has taken an OTA.
+ * In both cases, the device requires a full index.
+ *
+ * @param locale is the default for the device
+ * @param fingerprint id for the current build.
+ * @return true if a full index should be preformed.
+ */
+ @VisibleForTesting
+ boolean isFullIndex(Context context, String locale, String fingerprint,
+ String providerVersionedNames) {
+ final boolean isLocaleIndexed = IndexDatabaseHelper.isLocaleAlreadyIndexed(context, locale);
+ final boolean isBuildIndexed = IndexDatabaseHelper.isBuildIndexed(context, fingerprint);
+ final boolean areProvidersIndexed = IndexDatabaseHelper
+ .areProvidersIndexed(context, providerVersionedNames);
+
+ return !(isLocaleIndexed && isBuildIndexed && areProvidersIndexed);
+ }
+
+ /**
+ * Drop the currently stored database, and clear the flags which mark the database as indexed.
*/
private void rebuildDatabase() {
// Drop the database when the locale or build has changed. This eliminates rows which are
@@ -244,16 +221,9 @@ public class DatabaseIndexingManager {
* @param localeStr the default locale for the device.
*/
@VisibleForTesting
- void updateDatabase(boolean needsReindexing, String localeStr) {
- final UpdateData copy;
-
- synchronized (mDataToProcess) {
- copy = mDataToProcess.copy();
- mDataToProcess.clear();
- }
-
- final List dataToUpdate = copy.dataToUpdate;
- final Map> nonIndexableKeys = copy.nonIndexableKeys;
+ void updateDatabase(PreIndexData indexData, boolean needsReindexing, String localeStr) {
+ final List dataToUpdate = indexData.dataToUpdate;
+ final Map> nonIndexableKeys = indexData.nonIndexableKeys;
final SQLiteDatabase database = getWritableDatabase();
if (database == null) {
@@ -378,99 +348,10 @@ public class DatabaseIndexingManager {
disabledResults.close();
}
- @VisibleForTesting
- boolean addIndexablesFromRemoteProvider(String packageName, String authority) {
- try {
- final Context context = mBaseAuthority.equals(authority) ?
- mContext : mContext.createPackageContext(packageName, 0);
-
- final Uri uriForResources = buildUriForXmlResources(authority);
- addIndexablesForXmlResourceUri(context, packageName, uriForResources,
- SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS);
-
- final Uri uriForRawData = buildUriForRawData(authority);
- addIndexablesForRawDataUri(context, packageName, uriForRawData,
- SearchIndexablesContract.INDEXABLES_RAW_COLUMNS);
- return true;
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
- + Log.getStackTraceString(e));
- return false;
- }
- }
-
- @VisibleForTesting
- void addNonIndexablesKeysFromRemoteProvider(String packageName,
- String authority) {
- final List keys =
- getNonIndexablesKeysFromRemoteProvider(packageName, authority);
-
- addNonIndexableKeys(packageName, keys);
- }
-
- private List getNonIndexablesKeysFromRemoteProvider(String packageName,
- String authority) {
- try {
- final Context packageContext = mContext.createPackageContext(packageName, 0);
-
- final Uri uriForNonIndexableKeys = buildUriForNonIndexableKeys(authority);
- return getNonIndexablesKeys(packageContext, uriForNonIndexableKeys,
- SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(LOG_TAG, "Could not create context for " + packageName + ": "
- + Log.getStackTraceString(e));
- return EMPTY_LIST;
- }
- }
-
- private List getNonIndexablesKeys(Context packageContext, Uri uri,
- String[] projection) {
-
- final ContentResolver resolver = packageContext.getContentResolver();
- final Cursor cursor = resolver.query(uri, projection, null, null, null);
-
- if (cursor == null) {
- Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
- return EMPTY_LIST;
- }
-
- final List result = new ArrayList<>();
- try {
- final int count = cursor.getCount();
- if (count > 0) {
- while (cursor.moveToNext()) {
- final String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE);
-
- if (TextUtils.isEmpty(key) && Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
- Log.v(LOG_TAG, "Empty non-indexable key from: "
- + packageContext.getPackageName());
- continue;
- }
-
- result.add(key);
- }
- }
- return result;
- } finally {
- cursor.close();
- }
- }
-
- public void addIndexableData(SearchIndexableData data) {
- synchronized (mDataToProcess) {
- mDataToProcess.dataToUpdate.add(data);
- }
- }
-
- public void addNonIndexableKeys(String authority, List keys) {
- synchronized (mDataToProcess) {
- if (keys != null && !keys.isEmpty()) {
- mDataToProcess.nonIndexableKeys.put(authority, new ArraySet<>(keys));
- }
- }
- }
/**
+ * TODO (b/64951285): Deprecate this method
+ *
* Update the Index for a specific class name resources
*
* @param className the class name (typically a fragment name).
@@ -491,9 +372,9 @@ public class DatabaseIndexingManager {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- addIndexableData(res);
- updateDatabase(false, Locale.getDefault().toString());
- res.enabled = false;
+// addIndexableData(res);
+// updateDatabase(false, Locale.getDefault().toString());
+// res.enabled = false;
}
});
}
@@ -507,126 +388,9 @@ public class DatabaseIndexingManager {
}
}
- private static Uri buildUriForXmlResources(String authority) {
- return Uri.parse("content://" + authority + "/" +
- SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
- }
- private static Uri buildUriForRawData(String authority) {
- return Uri.parse("content://" + authority + "/" +
- SearchIndexablesContract.INDEXABLES_RAW_PATH);
- }
-
- private static Uri buildUriForNonIndexableKeys(String authority) {
- return Uri.parse("content://" + authority + "/" +
- SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
- }
-
- private void addIndexablesForXmlResourceUri(Context packageContext, String packageName,
- Uri uri, String[] projection) {
-
- final ContentResolver resolver = packageContext.getContentResolver();
- final Cursor cursor = resolver.query(uri, projection, null, null, null);
-
- if (cursor == null) {
- Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
- return;
- }
-
- try {
- final int count = cursor.getCount();
- if (count > 0) {
- while (cursor.moveToNext()) {
- final int xmlResId = cursor.getInt(COLUMN_INDEX_XML_RES_RESID);
-
- final String className = cursor.getString(COLUMN_INDEX_XML_RES_CLASS_NAME);
- final int iconResId = cursor.getInt(COLUMN_INDEX_XML_RES_ICON_RESID);
-
- final String action = cursor.getString(COLUMN_INDEX_XML_RES_INTENT_ACTION);
- final String targetPackage = cursor.getString(
- COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE);
- final String targetClass = cursor.getString(
- COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS);
-
- SearchIndexableResource sir = new SearchIndexableResource(packageContext);
- sir.xmlResId = xmlResId;
- sir.className = className;
- sir.packageName = packageName;
- sir.iconResId = iconResId;
- sir.intentAction = action;
- sir.intentTargetPackage = targetPackage;
- sir.intentTargetClass = targetClass;
-
- addIndexableData(sir);
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- private void addIndexablesForRawDataUri(Context packageContext, String packageName,
- Uri uri, String[] projection) {
-
- final ContentResolver resolver = packageContext.getContentResolver();
- final Cursor cursor = resolver.query(uri, projection, null, null, null);
-
- if (cursor == null) {
- Log.w(LOG_TAG, "Cannot add index data for Uri: " + uri.toString());
- return;
- }
-
- try {
- final int count = cursor.getCount();
- if (count > 0) {
- while (cursor.moveToNext()) {
- final int providerRank = cursor.getInt(COLUMN_INDEX_RAW_RANK);
- // TODO Remove rank
- final String title = cursor.getString(COLUMN_INDEX_RAW_TITLE);
- final String summaryOn = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
- final String summaryOff = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_OFF);
- final String entries = cursor.getString(COLUMN_INDEX_RAW_ENTRIES);
- final String keywords = cursor.getString(COLUMN_INDEX_RAW_KEYWORDS);
-
- final String screenTitle = cursor.getString(COLUMN_INDEX_RAW_SCREEN_TITLE);
-
- final String className = cursor.getString(COLUMN_INDEX_RAW_CLASS_NAME);
- final int iconResId = cursor.getInt(COLUMN_INDEX_RAW_ICON_RESID);
-
- final String action = cursor.getString(COLUMN_INDEX_RAW_INTENT_ACTION);
- final String targetPackage = cursor.getString(
- COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE);
- final String targetClass = cursor.getString(
- COLUMN_INDEX_RAW_INTENT_TARGET_CLASS);
-
- final String key = cursor.getString(COLUMN_INDEX_RAW_KEY);
- final int userId = cursor.getInt(COLUMN_INDEX_RAW_USER_ID);
-
- SearchIndexableRaw data = new SearchIndexableRaw(packageContext);
- data.title = title;
- data.summaryOn = summaryOn;
- data.summaryOff = summaryOff;
- data.entries = entries;
- data.keywords = keywords;
- data.screenTitle = screenTitle;
- data.className = className;
- data.packageName = packageName;
- data.iconResId = iconResId;
- data.intentAction = action;
- data.intentTargetPackage = targetPackage;
- data.intentTargetClass = targetClass;
- data.key = key;
- data.userId = userId;
-
- addIndexableData(data);
- }
- }
- } finally {
- cursor.close();
- }
- }
-
- public void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
+ @VisibleForTesting
+ void indexOneSearchIndexableData(SQLiteDatabase database, String localeStr,
SearchIndexableData data, Map> nonIndexableKeys) {
if (data instanceof SearchIndexableResource) {
indexOneResource(database, localeStr, (SearchIndexableResource) data, nonIndexableKeys);
@@ -1010,38 +774,6 @@ public class DatabaseIndexingManager {
}
}
- /**
- * A private class to describe the indexDatabase data for the Index database
- */
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- static class UpdateData {
- public List dataToUpdate;
- public List dataToDisable;
- public Map> nonIndexableKeys;
-
- public UpdateData() {
- dataToUpdate = new ArrayList<>();
- dataToDisable = new ArrayList<>();
- nonIndexableKeys = new HashMap<>();
- }
-
- public UpdateData(UpdateData other) {
- dataToUpdate = new ArrayList<>(other.dataToUpdate);
- dataToDisable = new ArrayList<>(other.dataToDisable);
- nonIndexableKeys = new HashMap<>(other.nonIndexableKeys);
- }
-
- public UpdateData copy() {
- return new UpdateData(this);
- }
-
- public void clear() {
- dataToUpdate.clear();
- dataToDisable.clear();
- nonIndexableKeys.clear();
- }
- }
-
public static class DatabaseRow {
public final String locale;
public final String updatedTitle;
diff --git a/src/com/android/settings/search/DatabaseIndexingUtils.java b/src/com/android/settings/search/DatabaseIndexingUtils.java
index 938ddb74b3f..7093134d769 100644
--- a/src/com/android/settings/search/DatabaseIndexingUtils.java
+++ b/src/com/android/settings/search/DatabaseIndexingUtils.java
@@ -174,35 +174,6 @@ public class DatabaseIndexingUtils {
return null;
}
- /**
- * Only allow a "well known" SearchIndexablesProvider. The provider should:
- *
- * - have read/write {@link Manifest.permission#READ_SEARCH_INDEXABLES}
- * - be from a privileged package
- */
- static boolean isWellKnownProvider(ResolveInfo info, Context context) {
- final String authority = info.providerInfo.authority;
- final String packageName = info.providerInfo.applicationInfo.packageName;
-
- if (TextUtils.isEmpty(authority) || TextUtils.isEmpty(packageName)) {
- return false;
- }
-
- final String readPermission = info.providerInfo.readPermission;
- final String writePermission = info.providerInfo.writePermission;
-
- if (TextUtils.isEmpty(readPermission) || TextUtils.isEmpty(writePermission)) {
- return false;
- }
-
- if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(readPermission) ||
- !android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(writePermission)) {
- return false;
- }
-
- return isPrivilegedPackage(packageName, context);
- }
-
static String normalizeHyphen(String input) {
return (input != null) ? input.replaceAll(NON_BREAKING_HYPHEN, HYPHEN) : EMPTY;
}
@@ -217,15 +188,4 @@ public class DatabaseIndexingUtils {
static String normalizeKeywords(String input) {
return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
}
-
- private static boolean isPrivilegedPackage(String packageName, Context context) {
- final PackageManager pm = context.getPackageManager();
- try {
- PackageInfo packInfo = pm.getPackageInfo(packageName, 0);
- return ((packInfo.applicationInfo.privateFlags
- & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
- } catch (PackageManager.NameNotFoundException e) {
- return false;
- }
- }
}
diff --git a/src/com/android/settings/search/DatabaseResultLoader.java b/src/com/android/settings/search/DatabaseResultLoader.java
index 7815a45ad2c..3d280b2002e 100644
--- a/src/com/android/settings/search/DatabaseResultLoader.java
+++ b/src/com/android/settings/search/DatabaseResultLoader.java
@@ -40,19 +40,19 @@ public class DatabaseResultLoader extends AsyncLoader providers) {
StringBuilder sb = new StringBuilder();
@@ -282,44 +268,42 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper {
return sb.toString();
}
- static void clearCachedIndexed(Context context) {
- context.getSharedPreferences(INDEX, Context.MODE_PRIVATE).edit().clear().commit();
- }
-
static void setLocaleIndexed(Context context, String locale) {
- context.getSharedPreferences(INDEX, Context.MODE_PRIVATE)
+ context.getSharedPreferences(SHARED_PREFS_TAG, Context.MODE_PRIVATE)
.edit()
.putBoolean(locale, true)
.apply();
}
static void setProvidersIndexed(Context context, String providerVersionedNames) {
- context.getSharedPreferences(INDEX, Context.MODE_PRIVATE)
+ context.getSharedPreferences(SHARED_PREFS_TAG, Context.MODE_PRIVATE)
.edit()
.putString(PREF_KEY_INDEXED_PROVIDERS, providerVersionedNames)
.apply();
}
static boolean isLocaleAlreadyIndexed(Context context, String locale) {
- return context.getSharedPreferences(INDEX, Context.MODE_PRIVATE).getBoolean(locale, false);
+ return context.getSharedPreferences(SHARED_PREFS_TAG, Context.MODE_PRIVATE)
+ .getBoolean(locale, false);
}
static boolean areProvidersIndexed(Context context, String providerVersionedNames) {
- final String indexedProviders = context.getSharedPreferences(INDEX, Context.MODE_PRIVATE)
- .getString(PREF_KEY_INDEXED_PROVIDERS, null);
+ final String indexedProviders =
+ context.getSharedPreferences(SHARED_PREFS_TAG, Context.MODE_PRIVATE)
+ .getString(PREF_KEY_INDEXED_PROVIDERS, null);
return TextUtils.equals(indexedProviders, providerVersionedNames);
}
static boolean isBuildIndexed(Context context, String buildNo) {
- return context.getSharedPreferences(INDEX, Context.MODE_PRIVATE).getBoolean(buildNo, false);
+ return context.getSharedPreferences(SHARED_PREFS_TAG,
+ Context.MODE_PRIVATE).getBoolean(buildNo, false);
}
static void setBuildIndexed(Context context, String buildNo) {
- context.getSharedPreferences(INDEX, 0).edit().putBoolean(buildNo, true).commit();
+ context.getSharedPreferences(SHARED_PREFS_TAG, 0).edit().putBoolean(buildNo, true).commit();
}
private void dropTables(SQLiteDatabase db) {
- clearCachedIndexed(mContext);
db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_META_INDEX);
db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_PREFS_INDEX);
db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SAVED_QUERIES);
diff --git a/src/com/android/settings/search/SearchFeatureProviderImpl.java b/src/com/android/settings/search/SearchFeatureProviderImpl.java
index 400cf8fe5f3..69c086f1659 100644
--- a/src/com/android/settings/search/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search/SearchFeatureProviderImpl.java
@@ -74,8 +74,7 @@ public class SearchFeatureProviderImpl implements SearchFeatureProvider {
@Override
public DatabaseIndexingManager getIndexingManager(Context context) {
if (mDatabaseIndexingManager == null) {
- mDatabaseIndexingManager = new DatabaseIndexingManager(context.getApplicationContext(),
- context.getPackageName());
+ mDatabaseIndexingManager = new DatabaseIndexingManager(context.getApplicationContext());
}
return mDatabaseIndexingManager;
}
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index d67e8eb23a5..044a00c6eb7 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -44,6 +44,7 @@ import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.datausage.DataPlanUsageSummary;
import com.android.settings.datausage.DataUsageMeteredSettings;
import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
import com.android.settings.development.DevelopmentSettings;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.deviceinfo.StorageSettings;
@@ -213,6 +214,10 @@ public final class SearchIndexableResources {
R.drawable.ic_settings_notifications);
addIndex(DreamSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_display);
addIndex(SupportDashboardActivity.class, NO_DATA_RES_ID, R.drawable.ic_help);
+ addIndex(
+ AutomaticStorageManagerSettings.class,
+ NO_DATA_RES_ID,
+ R.drawable.ic_settings_storage);
}
private SearchIndexableResources() {
diff --git a/src/com/android/settings/search/indexing/IndexableDataCollector.java b/src/com/android/settings/search/indexing/IndexableDataCollector.java
new file mode 100644
index 00000000000..cd6b9bbd2c0
--- /dev/null
+++ b/src/com/android/settings/search/indexing/IndexableDataCollector.java
@@ -0,0 +1,361 @@
+/*
+ * 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.indexing;
+
+import android.Manifest;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.SearchIndexableResource;
+import android.provider.SearchIndexablesContract;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settings.search.SettingsSearchIndexablesProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
+
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_CLASS_NAME;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ENTRIES;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_ACTION;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_CLASS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEY;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_KEYWORDS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_RANK;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SCREEN_TITLE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_OFF;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_TITLE;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_USER_ID;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
+import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
+
+/**
+ * Collects all data from {@link android.provider.SearchIndexablesProvider} to be indexed.
+ */
+public class IndexableDataCollector {
+
+ private static final String TAG = "IndexableDataCollector";
+
+ // TODO (b/64938328) update to new search package.
+ private final String BASE_AUTHORITY = "com.android.settings";
+
+ private static final List EMPTY_LIST = Collections.emptyList();
+
+ private Context mContext;
+
+ private PreIndexData mIndexData;
+
+ public IndexableDataCollector(Context context) {
+ mContext = context;
+ }
+
+ public PreIndexData collectIndexableData(List providers, boolean isFullIndex) {
+ mIndexData = new PreIndexData();
+
+ for (final ResolveInfo info : providers) {
+ if (!isWellKnownProvider(info)) {
+ continue;
+ }
+ final String authority = info.providerInfo.authority;
+ final String packageName = info.providerInfo.packageName;
+
+ if (isFullIndex) {
+ addIndexablesFromRemoteProvider(packageName, authority);
+ }
+
+ final long nonIndexableStartTime = System.currentTimeMillis();
+ addNonIndexablesKeysFromRemoteProvider(packageName, authority);
+ if (SettingsSearchIndexablesProvider.DEBUG) {
+ final long nonIndexableTime = System.currentTimeMillis() - nonIndexableStartTime;
+ Log.d(TAG, "performIndexing update non-indexable for package " + packageName
+ + " took time: " + nonIndexableTime);
+ }
+ }
+
+ return mIndexData;
+ }
+
+ private boolean addIndexablesFromRemoteProvider(String packageName, String authority) {
+ try {
+ final Context context = BASE_AUTHORITY.equals(authority) ?
+ mContext : mContext.createPackageContext(packageName, 0);
+
+ final Uri uriForResources = buildUriForXmlResources(authority);
+ mIndexData.dataToUpdate.addAll(getIndexablesForXmlResourceUri(context, packageName,
+ uriForResources, SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS));
+
+ final Uri uriForRawData = buildUriForRawData(authority);
+ mIndexData.dataToUpdate.addAll(getIndexablesForRawDataUri(context, packageName,
+ uriForRawData, SearchIndexablesContract.INDEXABLES_RAW_COLUMNS));
+ return true;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Could not create context for " + packageName + ": "
+ + Log.getStackTraceString(e));
+ return false;
+ }
+ }
+
+ @VisibleForTesting
+ List getIndexablesForXmlResourceUri(Context packageContext,
+ String packageName, Uri uri, String[] projection) {
+
+ final ContentResolver resolver = packageContext.getContentResolver();
+ final Cursor cursor = resolver.query(uri, projection, null, null, null);
+ List resources = new ArrayList<>();
+
+ if (cursor == null) {
+ Log.w(TAG, "Cannot add index data for Uri: " + uri.toString());
+ return resources;
+ }
+
+ try {
+ final int count = cursor.getCount();
+ if (count > 0) {
+ while (cursor.moveToNext()) {
+ final int xmlResId = cursor.getInt(COLUMN_INDEX_XML_RES_RESID);
+
+ final String className = cursor.getString(COLUMN_INDEX_XML_RES_CLASS_NAME);
+ final int iconResId = cursor.getInt(COLUMN_INDEX_XML_RES_ICON_RESID);
+
+ final String action = cursor.getString(COLUMN_INDEX_XML_RES_INTENT_ACTION);
+ final String targetPackage = cursor.getString(
+ COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE);
+ final String targetClass = cursor.getString(
+ COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS);
+
+ SearchIndexableResource sir = new SearchIndexableResource(packageContext);
+ sir.xmlResId = xmlResId;
+ sir.className = className;
+ sir.packageName = packageName;
+ sir.iconResId = iconResId;
+ sir.intentAction = action;
+ sir.intentTargetPackage = targetPackage;
+ sir.intentTargetClass = targetClass;
+
+ resources.add(sir);
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ return resources;
+ }
+
+ private void addNonIndexablesKeysFromRemoteProvider(String packageName,
+ String authority) {
+ final List keys =
+ getNonIndexablesKeysFromRemoteProvider(packageName, authority);
+
+ if (keys != null && !keys.isEmpty()) {
+ mIndexData.nonIndexableKeys.put(authority, new ArraySet<>(keys));
+ }
+ }
+
+ @VisibleForTesting
+ List getNonIndexablesKeysFromRemoteProvider(String packageName,
+ String authority) {
+ try {
+ final Context packageContext = mContext.createPackageContext(packageName, 0);
+
+ final Uri uriForNonIndexableKeys = buildUriForNonIndexableKeys(authority);
+ return getNonIndexablesKeys(packageContext, uriForNonIndexableKeys,
+ SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Could not create context for " + packageName + ": "
+ + Log.getStackTraceString(e));
+ return EMPTY_LIST;
+ }
+ }
+
+ @VisibleForTesting
+ Uri buildUriForXmlResources(String authority) {
+ return Uri.parse("content://" + authority + "/" +
+ SearchIndexablesContract.INDEXABLES_XML_RES_PATH);
+ }
+
+ @VisibleForTesting
+ Uri buildUriForRawData(String authority) {
+ return Uri.parse("content://" + authority + "/" +
+ SearchIndexablesContract.INDEXABLES_RAW_PATH);
+ }
+
+ @VisibleForTesting
+ Uri buildUriForNonIndexableKeys(String authority) {
+ return Uri.parse("content://" + authority + "/" +
+ SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH);
+ }
+
+ @VisibleForTesting
+ List getIndexablesForRawDataUri(Context packageContext, String packageName,
+ Uri uri, String[] projection) {
+ final ContentResolver resolver = packageContext.getContentResolver();
+ final Cursor cursor = resolver.query(uri, projection, null, null, null);
+ List rawData = new ArrayList<>();
+
+ if (cursor == null) {
+ Log.w(TAG, "Cannot add index data for Uri: " + uri.toString());
+ return rawData;
+ }
+
+ try {
+ final int count = cursor.getCount();
+ if (count > 0) {
+ while (cursor.moveToNext()) {
+ final int providerRank = cursor.getInt(COLUMN_INDEX_RAW_RANK);
+ // TODO Remove rank
+ final String title = cursor.getString(COLUMN_INDEX_RAW_TITLE);
+ final String summaryOn = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
+ final String summaryOff = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_OFF);
+ final String entries = cursor.getString(COLUMN_INDEX_RAW_ENTRIES);
+ final String keywords = cursor.getString(COLUMN_INDEX_RAW_KEYWORDS);
+
+ final String screenTitle = cursor.getString(COLUMN_INDEX_RAW_SCREEN_TITLE);
+
+ final String className = cursor.getString(COLUMN_INDEX_RAW_CLASS_NAME);
+ final int iconResId = cursor.getInt(COLUMN_INDEX_RAW_ICON_RESID);
+
+ final String action = cursor.getString(COLUMN_INDEX_RAW_INTENT_ACTION);
+ final String targetPackage = cursor.getString(
+ COLUMN_INDEX_RAW_INTENT_TARGET_PACKAGE);
+ final String targetClass = cursor.getString(
+ COLUMN_INDEX_RAW_INTENT_TARGET_CLASS);
+
+ final String key = cursor.getString(COLUMN_INDEX_RAW_KEY);
+ final int userId = cursor.getInt(COLUMN_INDEX_RAW_USER_ID);
+
+ SearchIndexableRaw data = new SearchIndexableRaw(packageContext);
+ data.title = title;
+ data.summaryOn = summaryOn;
+ data.summaryOff = summaryOff;
+ data.entries = entries;
+ data.keywords = keywords;
+ data.screenTitle = screenTitle;
+ data.className = className;
+ data.packageName = packageName;
+ data.iconResId = iconResId;
+ data.intentAction = action;
+ data.intentTargetPackage = targetPackage;
+ data.intentTargetClass = targetClass;
+ data.key = key;
+ data.userId = userId;
+
+ rawData.add(data);
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+
+ return rawData;
+ }
+
+ private List getNonIndexablesKeys(Context packageContext, Uri uri,
+ String[] projection) {
+
+ final ContentResolver resolver = packageContext.getContentResolver();
+ final Cursor cursor = resolver.query(uri, projection, null, null, null);
+ final List result = new ArrayList<>();
+
+ if (cursor == null) {
+ Log.w(TAG, "Cannot add index data for Uri: " + uri.toString());
+ return result;
+ }
+
+ try {
+ final int count = cursor.getCount();
+ if (count > 0) {
+ while (cursor.moveToNext()) {
+ final String key = cursor.getString(COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE);
+
+ if (TextUtils.isEmpty(key) && Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Empty non-indexable key from: "
+ + packageContext.getPackageName());
+ continue;
+ }
+
+ result.add(key);
+ }
+ }
+ return result;
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Only allow a "well known" SearchIndexablesProvider. The provider should:
+ *
+ * - have read/write {@link Manifest.permission#READ_SEARCH_INDEXABLES}
+ * - be from a privileged package
+ */
+ @VisibleForTesting
+ boolean isWellKnownProvider(ResolveInfo info) {
+ final String authority = info.providerInfo.authority;
+ final String packageName = info.providerInfo.applicationInfo.packageName;
+
+ if (TextUtils.isEmpty(authority) || TextUtils.isEmpty(packageName)) {
+ return false;
+ }
+
+ final String readPermission = info.providerInfo.readPermission;
+ final String writePermission = info.providerInfo.writePermission;
+
+ if (TextUtils.isEmpty(readPermission) || TextUtils.isEmpty(writePermission)) {
+ return false;
+ }
+
+ if (!android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(readPermission) ||
+ !android.Manifest.permission.READ_SEARCH_INDEXABLES.equals(writePermission)) {
+ return false;
+ }
+
+ return isPrivilegedPackage(packageName, mContext);
+ }
+
+ /**
+ * @return true if the {@param packageName} is privileged.
+ */
+ private boolean isPrivilegedPackage(String packageName, Context context) {
+ final PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo packInfo = pm.getPackageInfo(packageName, 0);
+ return ((packInfo.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/settings/search/indexing/PreIndexData.java b/src/com/android/settings/search/indexing/PreIndexData.java
new file mode 100644
index 00000000000..de3cf7ca273
--- /dev/null
+++ b/src/com/android/settings/search/indexing/PreIndexData.java
@@ -0,0 +1,55 @@
+/*
+ * 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.indexing;
+
+import android.provider.SearchIndexableData;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Holds Data sources for indexable data.
+ * TODO (b/33577327) add getters and setters for data.
+ */
+public class PreIndexData {
+ public List dataToUpdate;
+ public Map> nonIndexableKeys;
+
+ public PreIndexData() {
+ dataToUpdate = new ArrayList<>();
+ nonIndexableKeys = new HashMap<>();
+ }
+
+ public PreIndexData(PreIndexData other) {
+ dataToUpdate = new ArrayList<>(other.dataToUpdate);
+ nonIndexableKeys = new HashMap<>(other.nonIndexableKeys);
+ }
+
+ public PreIndexData copy() {
+ return new PreIndexData(this);
+ }
+
+ public void clear() {
+ dataToUpdate.clear();
+ nonIndexableKeys.clear();
+ }
+}
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
index aeee6ffa011..43f25f11977 100644
--- a/src/com/android/settings/wifi/ConfigureWifiSettings.java
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -78,7 +78,7 @@ public class ConfigureWifiSettings extends DashboardFragment {
final NetworkScoreManagerWrapper networkScoreManagerWrapper =
new NetworkScoreManagerWrapper(context.getSystemService(NetworkScoreManager.class));
mWifiWakeupPreferenceController = new WifiWakeupPreferenceController(
- context, getLifecycle(), networkScoreManagerWrapper);
+ context, getLifecycle());
mUseOpenWifiPreferenceController = new UseOpenWifiPreferenceController(context, this,
networkScoreManagerWrapper, getLifecycle());
final WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index b319703570f..ef6a650a8b0 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -38,6 +38,7 @@ import android.net.wifi.WpsInfo;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.HandlerThread;
+import android.os.PowerManager;
import android.os.Process;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
@@ -918,9 +919,8 @@ public class WifiSettings extends RestrictedSettingsFragment
getContentResolver(), Settings.Global.WIFI_WAKEUP_AVAILABLE, defaultWakeupAvailable)
== 1;
if (wifiWakeupAvailable) {
- boolean wifiWakeupEnabled = Settings.Global.getInt(
- getContentResolver(), Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1;
- mConfigureWifiSettingsPreference.setSummary(getString(wifiWakeupEnabled
+ mConfigureWifiSettingsPreference.setSummary(getString(
+ isWifiWakeupEnabled()
? R.string.wifi_configure_settings_preference_summary_wakeup_on
: R.string.wifi_configure_settings_preference_summary_wakeup_off));
}
@@ -935,6 +935,20 @@ public class WifiSettings extends RestrictedSettingsFragment
}
}
+ private boolean isWifiWakeupEnabled() {
+ PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ ContentResolver contentResolver = getContentResolver();
+ return Settings.Global.getInt(contentResolver,
+ Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1
+ && Settings.Global.getInt(contentResolver,
+ Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1
+ && Settings.Global.getInt(contentResolver,
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 0
+ && Settings.Global.getInt(contentResolver,
+ Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1
+ && !powerManager.isPowerSaveMode();
+ }
+
private void setOffMessage() {
final CharSequence title = getText(R.string.wifi_empty_list_wifi_off);
// Don't use WifiManager.isScanAlwaysAvailable() to check the Wi-Fi scanning mode. Instead,
diff --git a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
index 0017a5d7c4a..efb8aa6f84a 100644
--- a/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
+++ b/src/com/android/settings/wifi/WifiWakeupPreferenceController.java
@@ -44,13 +44,10 @@ public class WifiWakeupPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnResume, OnPause {
private static final String KEY_ENABLE_WIFI_WAKEUP = "enable_wifi_wakeup";
- private final NetworkScoreManagerWrapper mNetworkScoreManager;
private SettingObserver mSettingObserver;
- public WifiWakeupPreferenceController(
- Context context, Lifecycle lifecycle, NetworkScoreManagerWrapper networkScoreManager) {
+ public WifiWakeupPreferenceController(Context context, Lifecycle lifecycle) {
super(context);
- mNetworkScoreManager = networkScoreManager;
lifecycle.addObserver(this);
}
@@ -116,11 +113,9 @@ public class WifiWakeupPreferenceController extends AbstractPreferenceController
boolean networkRecommendationsEnabled = Settings.Global.getInt(
mContext.getContentResolver(),
Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1;
- boolean activeScorerSet = mNetworkScoreManager.getActiveScorerPackage() != null;
- enableWifiWakeup.setEnabled(
- networkRecommendationsEnabled && wifiScanningEnabled && activeScorerSet);
+ enableWifiWakeup.setEnabled(networkRecommendationsEnabled && wifiScanningEnabled);
- if (!activeScorerSet) {
+ if (!networkRecommendationsEnabled) {
enableWifiWakeup.setSummary(R.string.wifi_wakeup_summary_scoring_disabled);
} else if (!wifiScanningEnabled) {
enableWifiWakeup.setSummary(R.string.wifi_wakeup_summary_scanning_disabled);
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index a08536a94d5..e38064a4253 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -64,7 +64,6 @@ com.android.settings.notification.AppNotificationSettings
com.android.settings.deviceinfo.PrivateVolumeSettings
com.android.settings.users.AppRestrictionsFragment
com.android.settings.deviceinfo.PrivateVolumeUnmount
-com.android.settings.deletionhelper.AutomaticStorageManagerSettings
com.android.settings.notification.ZenAccessSettings
com.android.settings.accessibility.ToggleFontSizePreferenceFragment
com.android.settings.applications.PremiumSmsAccess
diff --git a/tests/robotests/src/android/service/oemlock/OemLockManager.java b/tests/robotests/src/android/service/oemlock/OemLockManager.java
index 7c015cf5051..c168089be4b 100644
--- a/tests/robotests/src/android/service/oemlock/OemLockManager.java
+++ b/tests/robotests/src/android/service/oemlock/OemLockManager.java
@@ -32,9 +32,6 @@ public class OemLockManager {
return false;
}
- public boolean canUserAllowOemUnlock() {
- return true;
- }
public boolean isOemUnlockAllowed() {
return false;
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
index a1db5de77e8..ac0720a246f 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePreferenceTest.java
@@ -42,6 +42,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doAnswer;
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;
@@ -98,11 +99,29 @@ public class BluetoothDevicePreferenceTest {
when(mCachedBluetoothDevice.isConnected()).thenReturn(false);
when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
when(mCachedBluetoothDevice.startPairing()).thenReturn(true);
+ when(mCachedBluetoothDevice.hasHumanReadableName()).thenReturn(true);
mPreference.onClicked();
verify(mMetricsFeatureProvider).action(
mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
+ verify(mMetricsFeatureProvider, never()).action(mContext,
+ MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
+ }
+
+ @Test
+ public void onClicked_deviceNotBonded_shouldLogBluetoothPairEventAndPairWithoutNameEvent() {
+ when(mCachedBluetoothDevice.isConnected()).thenReturn(false);
+ when(mCachedBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ when(mCachedBluetoothDevice.startPairing()).thenReturn(true);
+ when(mCachedBluetoothDevice.hasHumanReadableName()).thenReturn(false);
+
+ mPreference.onClicked();
+
+ verify(mMetricsFeatureProvider).action(
+ mContext, MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
+ verify(mMetricsFeatureProvider).action(mContext,
+ MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
index 77213f54cfe..68d33545bc1 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java
@@ -19,6 +19,7 @@ package com.android.settings.dashboard;
import android.support.annotation.NonNull;
import android.support.v7.util.DiffUtil;
import android.support.v7.util.ListUpdateCallback;
+import android.widget.RemoteViews;
import com.android.settings.TestConfig;
import com.android.settings.dashboard.conditional.AirplaneModeCondition;
@@ -35,6 +36,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -224,6 +226,28 @@ public class DashboardDataTest {
testDiffUtil(mDashboardDataWithOneConditions, mDashboardDataWithNoItems, testResultData);
}
+ @Test
+ public void testDiffUtil_typeSuggestedContainer_ResultDataNothingChanged() {
+ //Build testResultData
+ final List testResultData = new ArrayList<>();
+ testResultData.add(new ListUpdateResult.ResultData(
+ ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 0, 1));
+ Tile tile = new Tile();
+ tile.remoteViews = mock(RemoteViews.class);
+
+ DashboardData prevData = new DashboardData.Builder()
+ .setConditions(null)
+ .setCategory(null)
+ .setSuggestions(Arrays.asList(tile))
+ .build();
+ DashboardData currentData = new DashboardData.Builder()
+ .setConditions(null)
+ .setCategory(null)
+ .setSuggestions(Arrays.asList(tile))
+ .build();
+ testDiffUtil(prevData, currentData, testResultData);
+ }
+
/**
* Test when using the
* {@link com.android.settings.dashboard.DashboardData.ItemsDataDiffCallback}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
index 2687714a959..ea160dd355f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFragmentTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceManager;
@@ -158,6 +159,7 @@ public class DashboardFragmentTest {
@Test
public void tintTileIcon_hasMetadata_shouldReturnIconTintableMetadata() {
final Tile tile = new Tile();
+ tile.icon = mock(Icon.class);
final Bundle metaData = new Bundle();
tile.metaData = metaData;
@@ -168,10 +170,19 @@ public class DashboardFragmentTest {
assertThat(mTestFragment.tintTileIcon(tile)).isTrue();
}
+ @Test
+ public void tintTileIcon_noIcon_shouldReturnFalse() {
+ final Tile tile = new Tile();
+ final Bundle metaData = new Bundle();
+ tile.metaData = metaData;
+
+ assertThat(mTestFragment.tintTileIcon(tile)).isFalse();
+ }
@Test
public void tintTileIcon_noMetadata_shouldReturnPackageNameCheck() {
final Tile tile = new Tile();
+ tile.icon = mock(Icon.class);
final Intent intent = new Intent();
tile.intent = intent;
diff --git a/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java
new file mode 100644
index 00000000000..dd438ffd77b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deletionhelper/AutomaticStorageManagerDescriptionPreferenceControllerTest.java
@@ -0,0 +1,83 @@
+package com.android.settings.deletionhelper;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AutomaticStorageManagerDescriptionPreferenceControllerTest {
+ @Mock private PreferenceScreen mScreen;
+ @Mock private Preference mPreference;
+ private AutomaticStorageManagerDescriptionPreferenceController mController;
+ private Context mContext = RuntimeEnvironment.application;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mController = new AutomaticStorageManagerDescriptionPreferenceController(mContext);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ when(mPreference.getContext()).thenReturn(mContext);
+ }
+
+ @Test
+ public void displayPreference_asmDisabled_shouldHaveDescription() {
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setSummary(eq(R.string.automatic_storage_manager_text));
+ }
+
+ @Test
+ public void displayPreference_asmEnabledButUnused_shouldHaveDescription() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+ 1);
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setSummary(eq(R.string.automatic_storage_manager_text));
+ }
+
+ @Ignore("Robolectric doesn't do locale switching for date localization -- yet.")
+ @Test
+ @Config(qualifiers = "en")
+ public void displayPreference_asmEnabledAndUsed_shouldHaveDescriptionFilledOut() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+ 1);
+ Settings.Secure.putLong(
+ mContext.getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
+ 10);
+ Settings.Secure.putLong(
+ mContext.getContentResolver(),
+ Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
+ 43200000); // January 1, 1970 12:00:00 PM to avoid timezone issues.
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference)
+ .setSummary(eq("10.00B total made available\n\nLast ran on January 1, 1970"));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
index b2d259a1846..a87f563cc9e 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageDashboardFragmentTest.java
@@ -20,13 +20,18 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Activity;
import android.os.storage.StorageManager;
import android.provider.SearchIndexableResource;
+import android.util.SparseArray;
+import com.android.settings.deviceinfo.storage.CachedStorageValuesHelper;
+import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
import com.android.settingslib.drawer.CategoryKey;
import org.junit.Before;
@@ -68,6 +73,47 @@ public class StorageDashboardFragmentTest {
verify(activity).invalidateOptionsMenu();
}
+ @Test
+ public void test_cacheProviderProvidesValuesIfBothCached() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ PrivateStorageInfo info = new PrivateStorageInfo(0, 0);
+ when(helper.getCachedPrivateStorageInfo()).thenReturn(info);
+ SparseArray result = new SparseArray<>();
+ when(helper.getCachedAppsStorageResult()).thenReturn(result);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isEqualTo(info);
+ assertThat(mFragment.getAppsStorageResult()).isEqualTo(result);
+ }
+
+ @Test
+ public void test_cacheProviderDoesntProvideValuesIfAppsMissing() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ PrivateStorageInfo info = new PrivateStorageInfo(0, 0);
+ when(helper.getCachedPrivateStorageInfo()).thenReturn(info);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isNull();
+ assertThat(mFragment.getAppsStorageResult()).isNull();
+ }
+
+ @Test
+ public void test_cacheProviderDoesntProvideValuesIfVolumeInfoMissing() {
+ CachedStorageValuesHelper helper = mock(CachedStorageValuesHelper.class);
+ SparseArray result = new SparseArray<>();
+ when(helper.getCachedAppsStorageResult()).thenReturn(result);
+
+ mFragment.setCachedStorageValuesHelper(helper);
+ mFragment.initializeCachedValues();
+
+ assertThat(mFragment.getPrivateStorageInfo()).isNull();
+ assertThat(mFragment.getAppsStorageResult()).isNull();
+ }
+
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List indexRes =
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java
new file mode 100644
index 00000000000..154a7a1afbf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/CachedStorageValuesHelperTest.java
@@ -0,0 +1,295 @@
+/*
+ * 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.android.settings.deviceinfo.storage.CachedStorageValuesHelper.CACHE_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_APP_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_AUDIO_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_IMAGE_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_TOTAL_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.EXTERNAL_VIDEO_BYTES;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.FREE_BYTES_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.GAME_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.MUSIC_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.OTHER_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.PHOTO_APPS_SIZE_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.SHARED_PREFERENCES_NAME;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.TIMESTAMP_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.TOTAL_BYTES_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.USER_ID_KEY;
+import static com.android.settings.deviceinfo.storage.CachedStorageValuesHelper.VIDEO_APPS_SIZE_KEY;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.SparseArray;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.deviceinfo.PrivateStorageInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class CachedStorageValuesHelperTest {
+ private Context mContext;
+
+ @Mock private CachedStorageValuesHelper.Clock mMockClock;
+ private CachedStorageValuesHelper mCachedValuesHelper;
+ private SharedPreferences mSharedPreferences;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application.getApplicationContext();
+ mSharedPreferences = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 0);
+ mCachedValuesHelper = new CachedStorageValuesHelper(mContext, 0);
+ mCachedValuesHelper.mClock = mMockClock;
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_cachedValuesAreLoaded() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 6000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+
+ assertThat(info.freeBytes).isEqualTo(1000L);
+ assertThat(info.totalBytes).isEqualTo(6000L);
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_cachedValuesAreLoaded() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 1)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 222222)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+
+ StorageAsyncLoader.AppsStorageResult primaryResult = result.get(0);
+ assertThat(primaryResult.gamesSize).isEqualTo(1L);
+ assertThat(primaryResult.musicAppsSize).isEqualTo(10L);
+ assertThat(primaryResult.videoAppsSize).isEqualTo(100L);
+ assertThat(primaryResult.photosAppsSize).isEqualTo(1000L);
+ assertThat(primaryResult.otherAppsSize).isEqualTo(10000L);
+ assertThat(primaryResult.cacheSize).isEqualTo(100000L);
+ assertThat(primaryResult.externalStats.totalBytes).isEqualTo(222222L);
+ assertThat(primaryResult.externalStats.audioBytes).isEqualTo(22L);
+ assertThat(primaryResult.externalStats.videoBytes).isEqualTo(222L);
+ assertThat(primaryResult.externalStats.imageBytes).isEqualTo(2222L);
+ assertThat(primaryResult.externalStats.appBytes).isEqualTo(22222L);
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfDataIsStale() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000000L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfDataIsStale() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000000L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 0)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfWrongUser() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 1)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfWrongUser() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10001L);
+ mSharedPreferences
+ .edit()
+ .putLong(GAME_APPS_SIZE_KEY, 0)
+ .putLong(MUSIC_APPS_SIZE_KEY, 10)
+ .putLong(VIDEO_APPS_SIZE_KEY, 100)
+ .putLong(PHOTO_APPS_SIZE_KEY, 1000)
+ .putLong(OTHER_APPS_SIZE_KEY, 10000)
+ .putLong(CACHE_APPS_SIZE_KEY, 100000)
+ .putLong(EXTERNAL_TOTAL_BYTES, 2)
+ .putLong(EXTERNAL_AUDIO_BYTES, 22)
+ .putLong(EXTERNAL_VIDEO_BYTES, 222)
+ .putLong(EXTERNAL_IMAGE_BYTES, 2222)
+ .putLong(EXTERNAL_APP_BYTES, 22222)
+ .putLong(FREE_BYTES_KEY, 1000L)
+ .putLong(TOTAL_BYTES_KEY, 5000L)
+ .putInt(USER_ID_KEY, 1)
+ .putLong(TIMESTAMP_KEY, 10000L)
+ .apply();
+
+ SparseArray result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void getCachedPrivateStorageInfo_nullIfEmpty() throws Exception {
+ PrivateStorageInfo info = mCachedValuesHelper.getCachedPrivateStorageInfo();
+ assertThat(info).isNull();
+ }
+
+ @Test
+ public void getCachedAppsStorageResult_nullIfEmpty() throws Exception {
+ SparseArray result =
+ mCachedValuesHelper.getCachedAppsStorageResult();
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void cacheResult_succeeds() throws Exception {
+ when(mMockClock.getCurrentTime()).thenReturn(10000L);
+ final StorageStatsSource.ExternalStorageStats externalStats =
+ new StorageStatsSource.ExternalStorageStats(22222l, 2l, 20L, 200L, 2000L);
+ final StorageAsyncLoader.AppsStorageResult result =
+ new StorageAsyncLoader.AppsStorageResult();
+ result.gamesSize = 1L;
+ result.musicAppsSize = 10l;
+ result.videoAppsSize = 100L;
+ result.photosAppsSize = 1000L;
+ result.otherAppsSize = 10000L;
+ result.cacheSize = 100000l;
+ result.externalStats = externalStats;
+ final PrivateStorageInfo info = new PrivateStorageInfo(1000L, 6000L);
+
+ mCachedValuesHelper.cacheResult(info, result);
+
+ assertThat(mSharedPreferences.getLong(GAME_APPS_SIZE_KEY, -1)).isEqualTo(1L);
+ assertThat(mSharedPreferences.getLong(MUSIC_APPS_SIZE_KEY, -1)).isEqualTo(10L);
+ assertThat(mSharedPreferences.getLong(VIDEO_APPS_SIZE_KEY, -1)).isEqualTo(100L);
+ assertThat(mSharedPreferences.getLong(PHOTO_APPS_SIZE_KEY, -1)).isEqualTo(1000L);
+ assertThat(mSharedPreferences.getLong(OTHER_APPS_SIZE_KEY, -1)).isEqualTo(10000L);
+ assertThat(mSharedPreferences.getLong(CACHE_APPS_SIZE_KEY, -1)).isEqualTo(100000L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_TOTAL_BYTES, -1)).isEqualTo(22222L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_AUDIO_BYTES, -1)).isEqualTo(2L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_VIDEO_BYTES, -1)).isEqualTo(20L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_IMAGE_BYTES, -1)).isEqualTo(200L);
+ assertThat(mSharedPreferences.getLong(EXTERNAL_APP_BYTES, -1)).isEqualTo(2000L);
+ assertThat(mSharedPreferences.getLong(FREE_BYTES_KEY, -1)).isEqualTo(1000L);
+ assertThat(mSharedPreferences.getLong(TOTAL_BYTES_KEY, -1)).isEqualTo(6000L);
+ assertThat(mSharedPreferences.getInt(USER_ID_KEY, -1)).isEqualTo(0);
+ assertThat(mSharedPreferences.getLong(TIMESTAMP_KEY, -1)).isEqualTo(10000L);
+ };
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
index 1f5c9be1739..7ea42b8d07b 100644
--- a/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSettingsTest.java
@@ -32,6 +32,7 @@ import com.android.settingslib.core.AbstractPreferenceController;
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;
@@ -43,7 +44,7 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AssistGestureSettingsTest {
- @Mock
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private FakeFeatureFactory mFakeFeatureFactory;
private AssistGestureSettings mSettings;
@@ -51,6 +52,7 @@ public class AssistGestureSettingsTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest(mContext);
mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mSettings = new AssistGestureSettings();
}
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
index 70ed568447d..fff38c59322 100644
--- a/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
+++ b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
@@ -17,24 +17,20 @@
package com.android.settings.search;
-import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
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.anyList;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
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.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@@ -43,19 +39,18 @@ import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
-import android.database.MatrixCursor;
import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
import android.os.Build;
+import android.provider.SearchIndexableData;
import android.provider.SearchIndexableResource;
import android.util.ArrayMap;
import com.android.settings.R;
import com.android.settings.TestConfig;
+import com.android.settings.search.indexing.PreIndexData;
import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.testutils.shadow.ShadowDatabaseIndexingUtils;
import com.android.settings.testutils.shadow.ShadowRunnableAsyncTask;
import org.junit.After;
@@ -67,7 +62,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowContentResolver;
import java.util.ArrayList;
import java.util.Arrays;
@@ -84,8 +78,6 @@ import java.util.Set;
sdk = TestConfig.SDK_VERSION,
shadows = {
ShadowRunnableAsyncTask.class,
- ShadowDatabaseIndexingUtils.class,
- ShadowContentResolver.class
}
)
public class DatabaseIndexingManagerTest {
@@ -129,6 +121,8 @@ public class DatabaseIndexingManagerTest {
private DatabaseIndexingManager mManager;
private SQLiteDatabase mDb;
+ private final List FAKE_PROVIDER_LIST = new ArrayList<>();
+
@Mock
private PackageManager mPackageManager;
@@ -136,10 +130,12 @@ public class DatabaseIndexingManagerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
- mManager = spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
+ mManager = spy(new DatabaseIndexingManager(mContext));
mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(FAKE_PROVIDER_LIST).when(mPackageManager)
+ .queryIntentContentProviders(any(Intent.class), anyInt());
FakeFeatureFactory.setupForTest(mContext);
}
@@ -755,113 +751,60 @@ public class DatabaseIndexingManagerTest {
@Test
public void testPerformIndexing_fullIndex_getsDataFromProviders() {
- DummyProvider provider = new DummyProvider();
- provider.onCreate();
- ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
+ SearchIndexableRaw rawData = getFakeRaw();
+ PreIndexData data = getPreIndexData(rawData);
+ doReturn(data).when(mManager).getIndexDataFromProviders(anyList(), anyBoolean());
+ doReturn(true).when(mManager).isFullIndex(any(Context.class), anyString(), anyString(),
+ anyString());
- // Test that Indexables are added for Full indexing
- when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
- .thenReturn(getDummyResolveInfo());
+ mManager.performIndexing();
- DatabaseIndexingManager manager =
- spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
-
- manager.performIndexing();
-
- verify(manager).addIndexablesFromRemoteProvider(PACKAGE_ONE, AUTHORITY_ONE);
- verify(manager).updateDatabase(true /* isFullIndex */, Locale.getDefault().toString());
+ verify(mManager).updateDatabase(data, true /* isFullIndex */,
+ Locale.getDefault().toString());
}
@Test
- public void testPerformIndexing_incrementalIndex_noDataAdded() {
- final List providerInfo = getDummyResolveInfo();
- skipFullIndex(providerInfo);
- DummyProvider provider = new DummyProvider();
- provider.onCreate();
- ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
- // Test that Indexables are added for Full indexing
- when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
- .thenReturn(providerInfo);
-
+ public void testPerformIndexing_fullIndex_databaseDropped() {
+ // Initialize the Manager and force rebuild
DatabaseIndexingManager manager =
- spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
-
- manager.mDataToProcess.dataToUpdate.clear();
-
- manager.performIndexing();
-
- verify(manager, times(0)).addDataToDatabase(any(SQLiteDatabase.class), anyString(),
- anyList(), anyMap());
- verify(manager, times(0)).addIndexablesFromRemoteProvider(PACKAGE_ONE, AUTHORITY_ONE);
- verify(manager).updateDataInDatabase(any(SQLiteDatabase.class), anyMap());
- }
-
- @Test
- public void testPerformIndexing_localeChanged_databaseDropped() {
- DummyProvider provider = new DummyProvider();
- provider.onCreate();
- ShadowContentResolver.registerProvider(AUTHORITY_ONE, provider);
-
- // Test that Indexables are added for Full indexing
- when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
- .thenReturn(getDummyResolveInfo());
-
- // Initialize the Manager
- DatabaseIndexingManager manager =
- spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
+ spy(new DatabaseIndexingManager(mContext));
+ doReturn(false).when(mManager).isFullIndex(any(Context.class), anyString(), anyString(),
+ anyString());
// Insert data point which will be dropped
- final String oldTitle = "This is French";
- insertSpecialCase(oldTitle, true, "key");
-
- // Add a data point to be added by the indexing
- SearchIndexableRaw raw = new SearchIndexableRaw(mContext);
- final String newTitle = "This is English";
- raw.title = newTitle;
- manager.mDataToProcess.dataToUpdate.add(raw);
+ insertSpecialCase("Ceci n'est pas un pipe", true, "oui oui mon ami");
manager.performIndexing();
- // Assert that the New Title is inserted
- final Cursor newCursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE data_title = '" +
- newTitle + "'", null);
- assertThat(newCursor.getCount()).isEqualTo(1);
-
// Assert that the Old Title is no longer in the database, since it was dropped
- final Cursor oldCursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE data_title = '" +
- oldTitle + "'", null);
+ final Cursor oldCursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
+
assertThat(oldCursor.getCount()).isEqualTo(0);
}
@Test
- public void testPerformIndexing_onOta_FullIndex() {
- DummyProvider provider = new DummyProvider();
- provider.onCreate();
- ShadowContentResolver.registerProvider(
- AUTHORITY_ONE, provider
- );
+ public void testPerformIndexing_isfullIndex() {
+ SearchIndexableRaw rawData = getFakeRaw();
+ PreIndexData data = getPreIndexData(rawData);
+ doReturn(data).when(mManager).getIndexDataFromProviders(anyList(), anyBoolean());
+ doReturn(true).when(mManager).isFullIndex(any(Context.class), anyString(), anyString(),
+ anyString());
- // Test that Indexables are added for Full indexing
- when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
- .thenReturn(getDummyResolveInfo());
+ mManager.performIndexing();
- DatabaseIndexingManager manager =
- spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
-
- manager.performIndexing();
-
- verify(manager).updateDatabase(true /* isFullIndex */, Locale.getDefault().toString());
+ verify(mManager).updateDatabase(data, true /* isFullIndex */,
+ Locale.getDefault().toString());
}
@Test
- public void testPerformIndexing_onPackageChange_shouldFullIndex() {
+ public void testPerformIndexing_onPackageChange_fullIndex() {
final List providers = getDummyResolveInfo();
final String buildNumber = Build.FINGERPRINT;
final String locale = Locale.getDefault().toString();
skipFullIndex(providers);
// This snapshot is already indexed. Should return false
- assertThat(IndexDatabaseHelper.isFullIndex(
+ assertThat(mManager.isFullIndex(
mContext, locale, buildNumber,
IndexDatabaseHelper.buildProviderVersionedNames(providers)))
.isFalse();
@@ -869,65 +812,46 @@ public class DatabaseIndexingManagerTest {
// Change provider version number, this should trigger full index.
providers.get(0).providerInfo.applicationInfo.versionCode++;
- assertThat(IndexDatabaseHelper.isFullIndex(mContext, locale, buildNumber,
+ assertThat(mManager.isFullIndex(mContext, locale, buildNumber,
IndexDatabaseHelper.buildProviderVersionedNames(providers)))
.isTrue();
}
@Test
public void testPerformIndexing_onOta_buildNumberIsCached() {
- DummyProvider provider = new DummyProvider();
- provider.onCreate();
- ShadowContentResolver.registerProvider(
- AUTHORITY_ONE, provider
- );
+ mManager.performIndexing();
- // Test that Indexables are added for Full indexing
- when(mPackageManager.queryIntentContentProviders(any(Intent.class), anyInt()))
- .thenReturn(getDummyResolveInfo());
-
- DatabaseIndexingManager manager =
- spy(new DatabaseIndexingManager(mContext, PACKAGE_ONE));
-
- manager.performIndexing();
-
- assertThat(IndexDatabaseHelper.getInstance(mContext).isBuildIndexed(mContext,
- Build.FINGERPRINT)).isTrue();
+ assertThat(IndexDatabaseHelper.isBuildIndexed(mContext, Build.FINGERPRINT)).isTrue();
}
@Test
public void testFullUpdatedDatabase_noData_addDataToDatabaseNotCalled() {
- mManager.updateDatabase(true /* isFullIndex */, localeStr);
- mManager.mDataToProcess.dataToUpdate.clear();
+ PreIndexData emptydata = new PreIndexData();
+ mManager.updateDatabase(emptydata, true /* isFullIndex */, localeStr);
verify(mManager, times(0)).addDataToDatabase(any(SQLiteDatabase.class), anyString(),
anyList(), anyMap());
}
- @Test
- public void testFullUpdatedDatabase_updatedDataInDatabaseNotCalled() {
- mManager.updateDatabase(true /* isFullIndex */, localeStr);
- verify(mManager, times(0)).updateDataInDatabase(any(SQLiteDatabase.class), anyMap());
- }
-
@Test
public void testLocaleUpdated_afterIndexing_localeNotAdded() {
- mManager.updateDatabase(true /* isFullIndex */, localeStr);
- assertThat(IndexDatabaseHelper.getInstance(mContext)
- .isLocaleAlreadyIndexed(mContext, localeStr)).isFalse();
+ PreIndexData emptydata = new PreIndexData();
+ mManager.updateDatabase(emptydata, true /* isFullIndex */, localeStr);
+
+ assertThat(IndexDatabaseHelper.isLocaleAlreadyIndexed(mContext, localeStr)).isFalse();
}
@Test
public void testLocaleUpdated_afterFullIndexing_localeAdded() {
mManager.performIndexing();
- assertThat(IndexDatabaseHelper.getInstance(mContext)
- .isLocaleAlreadyIndexed(mContext, localeStr)).isTrue();
+ assertThat(IndexDatabaseHelper.isLocaleAlreadyIndexed(mContext, localeStr)).isTrue();
}
@Test
public void testUpdateDatabase_newEligibleData_addedToDatabase() {
// Test that addDataToDatabase is called when dataToUpdate is non-empty
- mManager.mDataToProcess.dataToUpdate.add(getFakeRaw());
- mManager.updateDatabase(true /* isFullIndex */, localeStr);
+ PreIndexData indexData = new PreIndexData();
+ indexData.dataToUpdate.add(getFakeRaw());
+ mManager.updateDatabase(indexData, true /* isFullIndex */, localeStr);
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index", null);
cursor.moveToPosition(0);
@@ -1020,8 +944,8 @@ public class DatabaseIndexingManagerTest {
@Test
public void testEmptyNonIndexableKeys_emptyDataKeyResources_addedToDatabase() {
insertSpecialCase(TITLE_ONE, true /* enabled */, null /* dataReferenceKey */);
-
- mManager.updateDatabase(false, localeStr);
+ PreIndexData emptydata = new PreIndexData();
+ mManager.updateDatabase(emptydata, false /* needsReindexing */, localeStr);
Cursor cursor = mDb.rawQuery("SELECT * FROM prefs_index WHERE enabled = 1", null);
cursor.moveToPosition(0);
@@ -1111,46 +1035,6 @@ public class DatabaseIndexingManagerTest {
return niks;
}
- private List getDummyResolveInfo() {
- List infoList = new ArrayList<>();
- ResolveInfo info = new ResolveInfo();
- info.providerInfo = new ProviderInfo();
- info.providerInfo.exported = true;
- info.providerInfo.authority = AUTHORITY_ONE;
- info.providerInfo.packageName = PACKAGE_ONE;
- info.providerInfo.applicationInfo = new ApplicationInfo();
- infoList.add(info);
-
- return infoList;
- }
-
- // TODO move this method and its counterpart in CursorToSearchResultConverterTest into
- // a util class with public fields to assert values.
- private Cursor getDummyCursor() {
- MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
- final String BLANK = "";
-
- ArrayList item =
- new ArrayList<>(INDEXABLES_RAW_COLUMNS.length);
- item.add("42"); // Rank
- item.add(TITLE_ONE); // Title
- item.add(BLANK); // Summary on
- item.add(BLANK); // summary off
- item.add(BLANK); // entries
- item.add(BLANK); // keywords
- item.add(BLANK); // screen title
- item.add(BLANK); // classname
- item.add("123"); // Icon
- item.add(BLANK); // Intent action
- item.add(BLANK); // target package
- item.add(BLANK); // target class
- item.add(KEY_ONE); // Key
- item.add("-1"); // userId
- cursor.addRow(item);
-
- return cursor;
- }
-
private void insertSpecialCase(String specialCase, boolean enabled, String key) {
ContentValues values = new ContentValues();
values.put(IndexDatabaseHelper.IndexColumns.DOCID, specialCase.hashCode());
@@ -1179,43 +1063,22 @@ public class DatabaseIndexingManagerTest {
mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX, null, values);
}
- private class DummyProvider extends ContentProvider {
+ private PreIndexData getPreIndexData(SearchIndexableData fakeData) {
+ PreIndexData data = new PreIndexData();
+ data.dataToUpdate.add(fakeData);
+ return data;
+ }
- @Override
- public boolean onCreate() {
- return false;
- }
+ private List getDummyResolveInfo() {
+ List infoList = new ArrayList<>();
+ ResolveInfo info = new ResolveInfo();
+ info.providerInfo = new ProviderInfo();
+ info.providerInfo.exported = true;
+ info.providerInfo.authority = AUTHORITY_ONE;
+ info.providerInfo.packageName = PACKAGE_ONE;
+ info.providerInfo.applicationInfo = new ApplicationInfo();
+ infoList.add(info);
- @Override
- public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
- @Nullable String selection, @Nullable String[] selectionArgs,
- @Nullable String sortOrder) {
- if (uri.toString().contains("xml")) {
- return null;
- }
- return getDummyCursor();
- }
-
- @Override
- public String getType(@NonNull Uri uri) {
- return null;
- }
-
- @Override
- public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
- return null;
- }
-
- @Override
- public int delete(@NonNull Uri uri, @Nullable String selection,
- @Nullable String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public int update(@NonNull Uri uri, @Nullable ContentValues values,
- @Nullable String selection, @Nullable String[] selectionArgs) {
- return 0;
- }
+ return infoList;
}
}
diff --git a/tests/robotests/src/com/android/settings/search/indexing/IndexableDataCollectorTest.java b/tests/robotests/src/com/android/settings/search/indexing/IndexableDataCollectorTest.java
new file mode 100644
index 00000000000..0f1f34524d4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search/indexing/IndexableDataCollectorTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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.indexing;
+
+import android.content.ContentResolver;
+import android.content.Context;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.provider.SearchIndexableResource;
+import com.android.settings.TestConfig;
+import com.android.settings.search.SearchIndexableRaw;
+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.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class IndexableDataCollectorTest {
+
+ private final String AUTHORITY_ONE = "authority";
+ private final String PACKAGE_ONE = "com.android.settings";
+
+ @Mock
+ ContentResolver mResolver;
+
+ Context mContext;
+
+ IndexableDataCollector mDataCollector;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mResolver).when(mContext).getContentResolver();
+ //doReturn(mPackageManager).when(mContext).getPackageManager();
+
+ mDataCollector = spy(new IndexableDataCollector(mContext));
+ }
+
+ @Test
+ public void testCollectIndexableData_addsResourceData() {
+ final List providerInfo = getDummyResolveInfo();
+ doReturn(true).when(mDataCollector).isWellKnownProvider(any(ResolveInfo.class));
+
+ List resources = getFakeResource();
+ doReturn(resources).when(mDataCollector).getIndexablesForXmlResourceUri(
+ any(Context.class), anyString(), any(Uri.class), any(String[].class));
+
+ PreIndexData data = mDataCollector.collectIndexableData(providerInfo,
+ true /* isFullIndex */);
+
+ assertThat(data.dataToUpdate).containsAllIn(resources);
+ }
+
+ @Test
+ public void testCollectIndexableData_addsRawData() {
+ final List providerInfo = getDummyResolveInfo();
+ doReturn(true).when(mDataCollector).isWellKnownProvider(any(ResolveInfo.class));
+
+ List rawData = getFakeRaw();
+ doReturn(rawData).when(mDataCollector).getIndexablesForRawDataUri(any(Context.class),
+ anyString(), any(Uri.class), any(String[].class));
+
+
+ PreIndexData data = mDataCollector.collectIndexableData(providerInfo,
+ true /* isFullIndex */);
+
+ assertThat(data.dataToUpdate).containsAllIn(rawData);
+ }
+
+ @Test
+ public void testCollectIndexableData_addsNonIndexables() {
+ final List providerInfo = getDummyResolveInfo();
+ doReturn(true).when(mDataCollector).isWellKnownProvider(any(ResolveInfo.class));
+
+ List niks = getFakeNonIndexables();
+
+ doReturn(niks).when(mDataCollector).getNonIndexablesKeysFromRemoteProvider(anyString(),
+ anyString());
+
+ PreIndexData data = mDataCollector.collectIndexableData(providerInfo,
+ true /* isFullIndex */);
+
+ assertThat(data.nonIndexableKeys.get(AUTHORITY_ONE)).containsAllIn(niks);
+ }
+
+ private List getDummyResolveInfo() {
+ List infoList = new ArrayList<>();
+ ResolveInfo info = new ResolveInfo();
+ info.providerInfo = new ProviderInfo();
+ info.providerInfo.exported = true;
+ info.providerInfo.authority = AUTHORITY_ONE;
+ info.providerInfo.packageName = PACKAGE_ONE;
+ info.providerInfo.applicationInfo = new ApplicationInfo();
+ infoList.add(info);
+
+ return infoList;
+ }
+
+ private List getFakeResource() {
+ List resources = new ArrayList<>();
+ final String BLANK = "";
+
+ SearchIndexableResource sir = new SearchIndexableResource(mContext);
+ sir.rank = 0;
+ sir.xmlResId = 0;
+ sir.className = BLANK;
+ sir.packageName = BLANK;
+ sir.iconResId = 0;
+ sir.intentAction = BLANK;
+ sir.intentTargetPackage = BLANK;
+ sir.intentTargetClass = BLANK;
+ sir.enabled = true;
+ resources.add(sir);
+
+ return resources;
+ }
+
+ private List getFakeRaw() {
+ List rawData = new ArrayList<>();
+
+ SearchIndexableRaw data = new SearchIndexableRaw(mContext);
+ data.title = "bront";
+ data.key = "brint";
+ rawData.add(data);
+
+ return rawData;
+ }
+
+ private List getFakeNonIndexables() {
+ List niks = new ArrayList<>();
+ niks.add("they're");
+ niks.add("good");
+ niks.add("dogs");
+ niks.add("brent");
+ return niks;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
index 8be686e64ea..306b297c69f 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/WifiWakeupPreferenceControllerTest.java
@@ -56,8 +56,6 @@ public class WifiWakeupPreferenceControllerTest {
private static final String TEST_SCORER_PACKAGE_NAME = "Test Scorer";
private Context mContext;
- @Mock
- private NetworkScoreManagerWrapper mNetworkScorer;
private WifiWakeupPreferenceController mController;
@Before
@@ -65,11 +63,11 @@ public class WifiWakeupPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new WifiWakeupPreferenceController(
- mContext, mock(Lifecycle.class), mNetworkScorer);
+ mContext, mock(Lifecycle.class));
Settings.System.putInt(mContext.getContentResolver(), WIFI_SCAN_ALWAYS_AVAILABLE, 1);
+ Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
SettingsShadowResources.overrideResource(
com.android.internal.R.integer.config_wifi_wakeup_available, 0);
- when(mNetworkScorer.getActiveScorerPackage()).thenReturn(TEST_SCORER_PACKAGE_NAME);
}
@After
@@ -116,9 +114,8 @@ public class WifiWakeupPreferenceControllerTest {
}
@Test
- public void updateState_preferenceSetCheckedAndSetEnabledWhenSettingsAreEnabled() {
+ public void updateState_preferenceSetCheckedAndSetEnabledWhenWakeupSettingEnabled() {
final SwitchPreference preference = mock(SwitchPreference.class);
- Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
Settings.System.putInt(mContext.getContentResolver(), WIFI_WAKEUP_ENABLED, 1);
mController.updateState(preference);
@@ -129,22 +126,20 @@ public class WifiWakeupPreferenceControllerTest {
}
@Test
- public void updateState_preferenceSetCheckedAndSetEnabledWhenSettingsAreDisabled() {
+ public void updateState_preferenceSetUncheckedAndSetEnabledWhenWakeupSettingDisabled() {
final SwitchPreference preference = mock(SwitchPreference.class);
- Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 0);
Settings.System.putInt(mContext.getContentResolver(), WIFI_WAKEUP_ENABLED, 0);
mController.updateState(preference);
verify(preference).setChecked(false);
- verify(preference).setEnabled(false);
+ verify(preference).setEnabled(true);
verify(preference).setSummary(R.string.wifi_wakeup_summary);
}
@Test
public void updateState_preferenceSetUncheckedAndSetDisabledWhenWifiScanningDisabled() {
final SwitchPreference preference = mock(SwitchPreference.class);
- Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
Settings.System.putInt(mContext.getContentResolver(), WIFI_WAKEUP_ENABLED, 1);
Settings.System.putInt(mContext.getContentResolver(), WIFI_SCAN_ALWAYS_AVAILABLE, 0);
@@ -158,9 +153,8 @@ public class WifiWakeupPreferenceControllerTest {
@Test
public void updateState_preferenceSetUncheckedAndSetDisabledWhenScoringDisabled() {
final SwitchPreference preference = mock(SwitchPreference.class);
- Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 1);
Settings.System.putInt(mContext.getContentResolver(), WIFI_WAKEUP_ENABLED, 1);
- when(mNetworkScorer.getActiveScorerPackage()).thenReturn(null);
+ Settings.System.putInt(mContext.getContentResolver(), NETWORK_RECOMMENDATIONS_ENABLED, 0);
mController.updateState(preference);