summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/location
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/location')
-rw-r--r--src/com/android/settings/location/LocationSettings.java21
-rw-r--r--src/com/android/settings/location/LocationSettingsBase.java29
-rw-r--r--src/com/android/settings/location/RecentLocationApps.java23
-rw-r--r--src/com/android/settings/location/SettingsInjector.java97
4 files changed, 102 insertions, 68 deletions
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 815be41..6dceea9 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -55,7 +55,7 @@ public class LocationSettings extends LocationSettingsBase
/** Key for preference category "Recent location requests" */
private static final String KEY_RECENT_LOCATION_REQUESTS = "recent_location_requests";
/** Key for preference category "Location services" */
- private static final String KEY_LOCATION_SERVICES = "location_services";
+ private static final String KEY_APP_SETTINGS = "app_settings";
private Switch mSwitch;
private boolean mValidListener;
@@ -165,10 +165,10 @@ public class LocationSettings extends LocationSettingsBase
categoryRecentLocationRequests.addPreference(banner);
}
- PreferenceCategory categoryLocationServices =
- (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES);
+ PreferenceCategory categoryAppSettings =
+ (PreferenceCategory) root.findPreference(KEY_APP_SETTINGS);
final SettingsInjector injector = new SettingsInjector(activity);
- List<Preference> locationServices = injector.getInjectedSettings();
+ List<Preference> appSettings = injector.getInjectedSettings();
mReceiver = new BroadcastReceiver() {
@Override
@@ -182,11 +182,11 @@ public class LocationSettings extends LocationSettingsBase
activity.registerReceiver(mReceiver,
new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED));
- if (locationServices.size() > 0) {
- addPreferencesSorted(locationServices, categoryLocationServices);
+ if (appSettings.size() > 0) {
+ addPreferencesSorted(appSettings, categoryAppSettings);
} else {
// If there's no item to display, remove the whole category.
- root.removePreference(categoryLocationServices);
+ root.removePreference(categoryAppSettings);
}
// Only show the master switch when we're not in multi-pane mode, and not being used as
@@ -233,9 +233,12 @@ public class LocationSettings extends LocationSettingsBase
break;
}
- boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF) && !restricted;
+ // Restricted user can't change the location mode, so disable the master switch. But in some
+ // corner cases, the location might still be enabled. In such case the master switch should
+ // be disabled but checked.
+ boolean enabled = (mode != Settings.Secure.LOCATION_MODE_OFF);
mSwitch.setEnabled(!restricted);
- mLocationMode.setEnabled(enabled);
+ mLocationMode.setEnabled(enabled && !restricted);
if (enabled != mSwitch.isChecked()) {
// set listener to null so that that code below doesn't trigger onCheckedChanged()
diff --git a/src/com/android/settings/location/LocationSettingsBase.java b/src/com/android/settings/location/LocationSettingsBase.java
index 81e841a..9ceefe7 100644
--- a/src/com/android/settings/location/LocationSettingsBase.java
+++ b/src/com/android/settings/location/LocationSettingsBase.java
@@ -38,12 +38,29 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
private static final int LOADER_ID_LOCATION_MODE = 1;
+ /**
+ * Whether the fragment is actively running.
+ */
+ private boolean mActive = false;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getLoaderManager().initLoader(LOADER_ID_LOCATION_MODE, null, this);
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ mActive = true;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mActive = false;
+ }
+
/** Called when location mode has changed. */
public abstract void onModeChanged(int mode, boolean restricted);
@@ -61,7 +78,9 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
}
mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
- onModeChanged(mode, true);
+ if (mActive) {
+ onModeChanged(mode, true);
+ }
return;
}
Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
@@ -69,9 +88,11 @@ public abstract class LocationSettingsBase extends SettingsPreferenceFragment
}
public void refreshLocationMode() {
- int mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF);
- onModeChanged(mode, isRestricted());
+ if (mActive) {
+ int mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
+ Settings.Secure.LOCATION_MODE_OFF);
+ onModeChanged(mode, isRestricted());
+ }
}
@Override
diff --git a/src/com/android/settings/location/RecentLocationApps.java b/src/com/android/settings/location/RecentLocationApps.java
index 23e6dcf..1fa8aac 100644
--- a/src/com/android/settings/location/RecentLocationApps.java
+++ b/src/com/android/settings/location/RecentLocationApps.java
@@ -140,7 +140,7 @@ public class RecentLocationApps {
public List<Preference> getAppList() {
// Retrieve Uid-based battery blaming info and generate a package to BatterySipper HashMap
// for later faster looking up.
- mStatsHelper.refreshStats();
+ mStatsHelper.refreshStats(true);
List<BatterySipper> usageList = mStatsHelper.getUsageList();
// Key: package Uid. Value: BatterySipperWrapper.
HashMap<Integer, BatterySipperWrapper> sipperMap =
@@ -243,11 +243,22 @@ public class RecentLocationApps {
try {
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
packageName, PackageManager.GET_META_DATA);
- pref = createRecentLocationEntry(
- mPackageManager.getApplicationIcon(appInfo),
- mPackageManager.getApplicationLabel(appInfo),
- highBattery,
- new PackageEntryClickedListener(packageName));
+ // Multiple users can install the same package. Each user gets a different Uid for
+ // the same package.
+ //
+ // Here we retrieve the Uid with package name, that will be the Uid for that package
+ // associated with the current active user. If the Uid differs from the Uid in ops,
+ // that means this entry belongs to another inactive user and we should ignore that.
+ if (appInfo.uid == ops.getUid()) {
+ pref = createRecentLocationEntry(
+ mPackageManager.getApplicationIcon(appInfo),
+ mPackageManager.getApplicationLabel(appInfo),
+ highBattery,
+ new PackageEntryClickedListener(packageName));
+ } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "package " + packageName + " with Uid " + ops.getUid() +
+ " belongs to another inactive account, ignored.");
+ }
} catch (PackageManager.NameNotFoundException e) {
Log.wtf(TAG, "Package not found: " + packageName);
}
diff --git a/src/com/android/settings/location/SettingsInjector.java b/src/com/android/settings/location/SettingsInjector.java
index 7bd190c..5929466 100644
--- a/src/com/android/settings/location/SettingsInjector.java
+++ b/src/com/android/settings/location/SettingsInjector.java
@@ -30,6 +30,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
+import android.os.SystemClock;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
@@ -42,7 +43,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -67,22 +67,6 @@ class SettingsInjector {
private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000;
/**
- * Intent action marking the receiver as injecting a setting
- */
- public static final String RECEIVER_INTENT = "com.android.settings.InjectedLocationSetting";
-
- /**
- * Name of the meta-data tag used to specify the resource file that includes the settings
- * attributes.
- */
- public static final String META_DATA_NAME = "com.android.settings.InjectedLocationSetting";
-
- /**
- * Name of the XML tag that includes the attributes for the setting.
- */
- public static final String ATTRIBUTES_NAME = "injected-location-setting";
-
- /**
* {@link Message#what} value for starting to load status values
* in case we aren't already in the process of loading them.
*/
@@ -115,7 +99,8 @@ class SettingsInjector {
/**
* Returns a list with one {@link InjectedSetting} object for each {@link android.app.Service}
- * that responds to {@link #RECEIVER_INTENT} and provides the expected setting metadata.
+ * that responds to {@link SettingInjectorService#ACTION_SERVICE_INTENT} and provides the
+ * expected setting metadata.
*
* Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
*
@@ -123,37 +108,38 @@ class SettingsInjector {
*/
private List<InjectedSetting> getSettings() {
PackageManager pm = mContext.getPackageManager();
- Intent receiverIntent = new Intent(RECEIVER_INTENT);
+ Intent intent = new Intent(SettingInjectorService.ACTION_SERVICE_INTENT);
List<ResolveInfo> resolveInfos =
- pm.queryIntentServices(receiverIntent, PackageManager.GET_META_DATA);
+ pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Found services: " + resolveInfos);
}
List<InjectedSetting> settings = new ArrayList<InjectedSetting>(resolveInfos.size());
- for (ResolveInfo receiver : resolveInfos) {
+ for (ResolveInfo resolveInfo : resolveInfos) {
try {
- InjectedSetting info = parseServiceInfo(receiver, pm);
- if (info == null) {
- Log.w(TAG, "Unable to load service info " + receiver);
+ InjectedSetting setting = parseServiceInfo(resolveInfo, pm);
+ if (setting == null) {
+ Log.w(TAG, "Unable to load service info " + resolveInfo);
} else {
- if (Log.isLoggable(TAG, Log.INFO)) {
- Log.i(TAG, "Loaded service info: " + info);
- }
- settings.add(info);
+ settings.add(setting);
}
} catch (XmlPullParserException e) {
- Log.w(TAG, "Unable to load service info " + receiver, e);
+ Log.w(TAG, "Unable to load service info " + resolveInfo, e);
} catch (IOException e) {
- Log.w(TAG, "Unable to load service info " + receiver, e);
+ Log.w(TAG, "Unable to load service info " + resolveInfo, e);
}
}
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Loaded settings: " + settings);
+ }
return settings;
}
/**
- * Parses {@link InjectedSetting} from the attributes of the {@link #META_DATA_NAME} tag.
+ * Parses {@link InjectedSetting} from the attributes of the
+ * {@link SettingInjectorService#META_DATA_NAME} tag.
*
* Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
*/
@@ -164,9 +150,9 @@ class SettingsInjector {
XmlResourceParser parser = null;
try {
- parser = si.loadXmlMetaData(pm, META_DATA_NAME);
+ parser = si.loadXmlMetaData(pm, SettingInjectorService.META_DATA_NAME);
if (parser == null) {
- throw new XmlPullParserException("No " + META_DATA_NAME
+ throw new XmlPullParserException("No " + SettingInjectorService.META_DATA_NAME
+ " meta-data for " + service + ": " + si);
}
@@ -178,9 +164,9 @@ class SettingsInjector {
}
String nodeName = parser.getName();
- if (!ATTRIBUTES_NAME.equals(nodeName)) {
+ if (!SettingInjectorService.ATTRIBUTES_NAME.equals(nodeName)) {
throw new XmlPullParserException("Meta-data does not start with "
- + ATTRIBUTES_NAME + " tag");
+ + SettingInjectorService.ATTRIBUTES_NAME + " tag");
}
Resources res = pm.getResourcesForApplication(si.applicationInfo);
@@ -201,15 +187,15 @@ class SettingsInjector {
private static InjectedSetting parseAttributes(
String packageName, String className, Resources res, AttributeSet attrs) {
- TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.InjectedLocationSetting);
+ TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.SettingInjectorService);
try {
// Note that to help guard against malicious string injection, we do not allow dynamic
// specification of the label (setting title)
- final String label = sa.getString(android.R.styleable.InjectedLocationSetting_label);
+ final String label = sa.getString(android.R.styleable.SettingInjectorService_title);
final int iconId = sa.getResourceId(
- android.R.styleable.InjectedLocationSetting_icon, 0);
+ android.R.styleable.SettingInjectorService_icon, 0);
final String settingsActivity =
- sa.getString(android.R.styleable.InjectedLocationSetting_settingsActivity);
+ sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "parsed label: " + label + ", iconId: " + iconId
+ ", settingsActivity: " + settingsActivity);
@@ -306,6 +292,7 @@ class SettingsInjector {
break;
case WHAT_RECEIVED_STATUS:
final Setting receivedSetting = (Setting) msg.obj;
+ receivedSetting.maybeLogElapsedTime();
mSettingsBeingLoaded.remove(receivedSetting);
mTimedOutSettings.remove(receivedSetting);
removeMessages(WHAT_TIMEOUT, receivedSetting);
@@ -357,8 +344,7 @@ class SettingsInjector {
iter.remove();
// Request the status value
- Intent intent = setting.createUpdatingIntent();
- mContext.startService(intent);
+ setting.startService();
mSettingsBeingLoaded.add(setting);
// Ensure that if receiving the status value takes too long, we start loading the
@@ -390,6 +376,7 @@ class SettingsInjector {
public final InjectedSetting setting;
public final Preference preference;
+ public long startMillis;
private Setting(InjectedSetting setting, Preference preference) {
this.setting = setting;
@@ -406,7 +393,7 @@ class SettingsInjector {
/**
* Returns true if they both have the same {@link #setting} value. Ignores mutable
- * preference so that it's safe to use in sets.
+ * {@link #preference} and {@link #startMillis} so that it's safe to use in sets.
*/
@Override
public boolean equals(Object o) {
@@ -419,11 +406,10 @@ class SettingsInjector {
}
/**
- * Creates an Intent to ask the receiver for the current status for the setting, and display
- * it when it replies.
+ * Starts the service to fetch for the current status for the setting, and updates the
+ * preference when the service replies.
*/
- public Intent createUpdatingIntent() {
- final Intent receiverIntent = setting.getServiceIntent();
+ public void startService() {
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -440,12 +426,25 @@ class SettingsInjector {
}
};
Messenger messenger = new Messenger(handler);
- receiverIntent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);
+
+ Intent intent = setting.getServiceIntent();
+ intent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);
+
if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, setting + ": sending rcv-intent: " + receiverIntent
+ Log.d(TAG, setting + ": sending update intent: " + intent
+ ", handler: " + handler);
+ startMillis = SystemClock.elapsedRealtime();
+ } else {
+ startMillis = 0;
+ }
+ mContext.startService(intent);
+ }
+
+ public void maybeLogElapsedTime() {
+ if (Log.isLoggable(TAG, Log.DEBUG) && startMillis != 0) {
+ long end = SystemClock.elapsedRealtime();
+ Log.d(TAG, this + " update took " + (end - startMillis) + " millis");
}
- return receiverIntent;
}
}
}