diff options
author | Lifu Tang <lifu@google.com> | 2013-08-20 19:40:44 -0700 |
---|---|---|
committer | Lifu Tang <lifu@google.com> | 2013-08-21 16:52:14 -0700 |
commit | 25518c3b45827537b2b2c2b35fdc86bc8bd60502 (patch) | |
tree | 3fb8c4e9ea1c7be3a1deaf1ea9e28c0c8af674c5 /src | |
parent | e873aeb3a659ac970609cebb5ec2f460afd1206a (diff) | |
download | packages_apps_Settings-25518c3b45827537b2b2c2b35fdc86bc8bd60502.zip packages_apps_Settings-25518c3b45827537b2b2c2b35fdc86bc8bd60502.tar.gz packages_apps_Settings-25518c3b45827537b2b2c2b35fdc86bc8bd60502.tar.bz2 |
Sort "Location services" alphabetically
* Sort "Location services" items by title
* Throttle the rate of loading status messages
Change-Id: Iecb039a4ab94a810e11ef3e426e4a4b5c8c75c37
Diffstat (limited to 'src')
3 files changed, 123 insertions, 57 deletions
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 3ab6c50..4970d37 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -23,6 +23,8 @@ import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; +import android.preference.PreferenceGroup; +import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.provider.Settings; import android.view.Gravity; @@ -32,6 +34,10 @@ import android.widget.Switch; import com.android.settings.R; import com.android.settings.fuelgauge.BatteryStatsHelper; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + /** * Location access settings. */ @@ -97,7 +103,21 @@ public class LocationSettings extends LocationSettingsBase mStatsHelper.destroy(); } + private void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) { + // If there's some items to display, sort the items and add them to the container. + Collections.sort(prefs, new Comparator<Preference>() { + @Override + public int compare(Preference lhs, Preference rhs) { + return lhs.getTitle().toString().compareTo(rhs.getTitle().toString()); + } + }); + for (Preference entry : prefs) { + container.addPreference(entry); + } + } + private PreferenceScreen createPreferenceHierarchy() { + final PreferenceActivity activity = (PreferenceActivity) getActivity(); PreferenceScreen root = getPreferenceScreen(); if (root != null) { root.removeAll(); @@ -110,7 +130,6 @@ public class LocationSettings extends LocationSettingsBase new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - PreferenceActivity activity = (PreferenceActivity) getActivity(); activity.startPreferencePanel( LocationMode.class.getName(), null, R.string.location_mode_screen_title, null, LocationSettings.this, @@ -118,15 +137,28 @@ public class LocationSettings extends LocationSettingsBase return true; } }); + + final PreferenceManager preferenceManager = getPreferenceManager(); + mRecentLocationRequests = (PreferenceCategory) root.findPreference(KEY_RECENT_LOCATION_REQUESTS); - mLocationServices = (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES); - - PreferenceActivity activity = (PreferenceActivity) getActivity(); RecentLocationApps recentApps = new RecentLocationApps(activity, mStatsHelper); - recentApps.fillAppList(mRecentLocationRequests); + List<Preference> recentLocationRequests = recentApps.getAppList(preferenceManager); + if (recentLocationRequests.size() > 0) { + addPreferencesSorted(recentLocationRequests, mRecentLocationRequests); + } else { + // If there's no item to display, add a "No recent apps" item. + PreferenceScreen screen = preferenceManager.createPreferenceScreen(activity); + screen.setTitle(R.string.location_no_recent_apps); + screen.setSelectable(false); + screen.setEnabled(false); + mRecentLocationRequests.addPreference(screen); + } - SettingsInjector.addInjectedSettings(mLocationServices, activity, getPreferenceManager()); + mLocationServices = (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES); + List<Preference> locationServices = SettingsInjector.getInjectedSettings( + activity, preferenceManager); + addPreferencesSorted(locationServices, mLocationServices); // Only show the master switch when we're not in multi-pane mode, and not being used as // Setup Wizard. @@ -174,7 +206,6 @@ public class LocationSettings extends LocationSettingsBase boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF); mLocationMode.setEnabled(enabled); - mRecentLocationRequests.setEnabled(enabled); mLocationServices.setEnabled(enabled); if (enabled != mSwitch.isChecked()) { diff --git a/src/com/android/settings/location/RecentLocationApps.java b/src/com/android/settings/location/RecentLocationApps.java index 9a59563..cbf8351 100644 --- a/src/com/android/settings/location/RecentLocationApps.java +++ b/src/com/android/settings/location/RecentLocationApps.java @@ -24,7 +24,6 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.preference.Preference; import android.preference.PreferenceActivity; -import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.util.Log; @@ -35,8 +34,6 @@ import com.android.settings.fuelgauge.BatterySipper; import com.android.settings.fuelgauge.BatteryStatsHelper; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -143,7 +140,7 @@ public class RecentLocationApps { * Fills a list of applications which queried location recently within * specified time. */ - public void fillAppList(PreferenceCategory container) { + public List<Preference> getAppList(PreferenceManager preferenceManager) { // Retrieve Uid-based battery blaming info and generate a package to BatterySipper HashMap // for later faster looking up. mStatsHelper.refreshStats(); @@ -166,10 +163,9 @@ public class RecentLocationApps { AppOpsManager.OP_MONITOR_LOCATION, AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, }); - PreferenceManager preferenceManager = container.getPreferenceManager(); // Process the AppOps list and generate a preference list. - ArrayList<PreferenceScreen> prefs = new ArrayList<PreferenceScreen>(); + ArrayList<Preference> prefs = new ArrayList<Preference>(); long now = System.currentTimeMillis(); for (AppOpsManager.PackageOps ops : appOps) { BatterySipperWrapper wrapper = sipperMap.get(ops.getUid()); @@ -179,25 +175,7 @@ public class RecentLocationApps { } } - if (prefs.size() > 0) { - // If there's some items to display, sort the items and add them to the container. - Collections.sort(prefs, new Comparator<PreferenceScreen>() { - @Override - public int compare(PreferenceScreen lhs, PreferenceScreen rhs) { - return lhs.getTitle().toString().compareTo(rhs.getTitle().toString()); - } - }); - for (PreferenceScreen entry : prefs) { - container.addPreference(entry); - } - } else { - // If there's no item to display, add a "No recent apps" item. - PreferenceScreen screen = preferenceManager.createPreferenceScreen(mActivity); - screen.setTitle(R.string.location_no_recent_apps); - screen.setSelectable(false); - screen.setEnabled(false); - container.addPreference(screen); - } + return prefs; } /** diff --git a/src/com/android/settings/location/SettingsInjector.java b/src/com/android/settings/location/SettingsInjector.java index ea760f5..0b7c172 100644 --- a/src/com/android/settings/location/SettingsInjector.java +++ b/src/com/android/settings/location/SettingsInjector.java @@ -16,7 +16,6 @@ package com.android.settings.location; -import android.R; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -32,7 +31,6 @@ import android.os.Handler; import android.os.Message; import android.os.Messenger; import android.preference.Preference; -import android.preference.PreferenceGroup; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.text.TextUtils; @@ -42,6 +40,8 @@ import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import com.android.settings.R; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -61,9 +61,10 @@ import java.util.List; * {@link SettingInjectorService#UPDATE_INTENT}. */ class SettingsInjector { - private static final String TAG = "SettingsInjector"; + private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000; + /** * Intent action marking the receiver as injecting a setting */ @@ -86,8 +87,6 @@ class SettingsInjector { * * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}. * - * TODO: sort alphabetically - * * TODO: unit test */ public static List<InjectedSetting> getSettings(Context context) { @@ -167,15 +166,17 @@ class SettingsInjector { private static InjectedSetting parseAttributes( String packageName, String className, Resources res, AttributeSet attrs) { - TypedArray sa = res.obtainAttributes(attrs, R.styleable.InjectedLocationSetting); + TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.InjectedLocationSetting); try { // Note that to help guard against malicious string injection, we do not allow dynamic // specification of the label (setting title) - final int labelId = sa.getResourceId(R.styleable.InjectedLocationSetting_label, 0); - final String label = sa.getString(R.styleable.InjectedLocationSetting_label); - final int iconId = sa.getResourceId(R.styleable.InjectedLocationSetting_icon, 0); + final int labelId = sa.getResourceId( + android.R.styleable.InjectedLocationSetting_label, 0); + final String label = sa.getString(android.R.styleable.InjectedLocationSetting_label); + final int iconId = sa.getResourceId( + android.R.styleable.InjectedLocationSetting_icon, 0); final String settingsActivity = - sa.getString(R.styleable.InjectedLocationSetting_settingsActivity); + sa.getString(android.R.styleable.InjectedLocationSetting_settingsActivity); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "parsed labelId: " + labelId + ", label: " + label + ", iconId: " + iconId); @@ -190,32 +191,84 @@ class SettingsInjector { } } + private static final class StatusLoader { + private final Context mContext; + private final Intent mIntent; + private final StatusLoader mPrev; + + private boolean mLoaded = false; + + /** + * Creates a loader and chains with the previous loader. + */ + public StatusLoader(Context context, Intent intent, StatusLoader prev) { + mContext = context; + mIntent = intent; + mPrev = prev; + } + + /** + * If the current message hasn't been loaded, loads the status messages + * and set time out for the next message. + */ + public void loadIfNotLoaded() { + if (mLoaded) { + return; + } + + mContext.startService(mIntent); + if (mPrev != null) { + Handler handler = new Handler() { + @Override + public void handleMessage(Message msg) { + // Continue with the next item in the chain. + mPrev.loadIfNotLoaded(); + } + }; + // Ensure that we start loading the previous setting in the chain if the current + // setting hasn't loaded before the timeout + handler.sendMessageDelayed( + Message.obtain(handler), INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS); + } + mLoaded = true; + } + } + /** - * Add settings that other apps have injected. + * Gets a list of preferences that other apps have injected. + * + * TODO: extract InjectedLocationSettingGetter that returns an iterable over + * InjectedSetting objects, so that this class can focus on UI */ - public static void addInjectedSettings(PreferenceGroup group, Context context, + public static List<Preference> getInjectedSettings(Context context, PreferenceManager preferenceManager) { Iterable<InjectedSetting> settings = getSettings(context); + ArrayList<Preference> prefs = new ArrayList<Preference>(); + StatusLoader loader = null; for (InjectedSetting setting : settings) { - Preference pref = addServiceSetting(context, group, setting, preferenceManager); + Preference pref = addServiceSetting(context, prefs, setting, preferenceManager); + Intent intent = createUpdatingIntent(context, pref, setting, loader); + loader = new StatusLoader(context, intent, loader); + } - // TODO: to prevent churn from multiple live broadcast receivers, don't trigger - // the next update until the sooner of: the current update completes or 1-2 seconds - // after the current update was started. - updateSetting(context, pref, setting); + // Start a thread to load each list item status. + if (loader != null) { + loader.loadIfNotLoaded(); } + + return prefs; } /** * Adds an injected setting to the root with status "Loading...". */ private static PreferenceScreen addServiceSetting(Context context, - PreferenceGroup group, InjectedSetting info, PreferenceManager preferenceManager) { + List<Preference> prefs, InjectedSetting info, PreferenceManager preferenceManager) { PreferenceScreen screen = preferenceManager.createPreferenceScreen(context); screen.setTitle(info.title); - screen.setSummary("Loading..."); + screen.setSummary(R.string.location_loading_injected_setting); PackageManager pm = context.getPackageManager(); Drawable icon = pm.getDrawable(info.packageName, info.iconId, null); screen.setIcon(icon); @@ -224,15 +277,17 @@ class SettingsInjector { settingIntent.setClassName(info.packageName, info.settingsActivity); screen.setIntent(settingIntent); - group.addPreference(screen); + prefs.add(screen); return screen; } /** - * Ask the receiver for the current status for the setting, and display it when it replies. + * Creates an Intent to ask the receiver for the current status for the setting, and display it + * when it replies. */ - private static void updateSetting(Context context, - final Preference pref, final InjectedSetting info) { + private static Intent createUpdatingIntent(Context context, + final Preference pref, final InjectedSetting info, final StatusLoader prev) { + final Intent receiverIntent = info.getServiceIntent(); Handler handler = new Handler() { @Override public void handleMessage(Message msg) { @@ -244,14 +299,16 @@ class SettingsInjector { } pref.setSummary(status); pref.setEnabled(enabled); + if (prev != null) { + prev.loadIfNotLoaded(); + } } }; Messenger messenger = new Messenger(handler); - Intent receiverIntent = info.getServiceIntent(); receiverIntent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger); if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, info + ": sending rcv-intent: " + receiverIntent + ", handler: " + handler); } - context.startService(receiverIntent); + return receiverIntent; } } |