From 88afb32fc6422139dcf8340aa88f3de9112a1485 Mon Sep 17 00:00:00 2001 From: Lifu Tang Date: Wed, 7 Aug 2013 11:18:16 -0700 Subject: [PATCH] Displays a list of most recent location apps Change-Id: I8e34ca8c30f308744022f17fac2444a496abd9e6 (cherry picked from commit 16ab0eca74751c331c1c74612548a27735a450b7) --- res/values/strings.xml | 4 + .../settings/location/LocationSettings.java | 6 + .../settings/location/RecentLocationApps.java | 117 ++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 src/com/android/settings/location/RecentLocationApps.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 6b9cf74e417..2211f4fd5f2 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2368,6 +2368,10 @@ Recent location requests Location services + + High battery use + + Low battery use Location mode diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 1f012e4307d..97907ded1d2 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -36,8 +36,11 @@ import com.android.settings.R; public class LocationSettings extends LocationSettingsBase implements CompoundButton.OnCheckedChangeListener { private static final String TAG = LocationSettings.class.getSimpleName(); + /** Key for preference screen "Mode" */ private static final String KEY_LOCATION_MODE = "location_mode"; + /** 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 Switch mSwitch; @@ -100,6 +103,9 @@ public class LocationSettings extends LocationSettingsBase Activity activity = getActivity(); + RecentLocationApps recentApps = new RecentLocationApps(activity); + recentApps.fillAppList(mRecentLocationRequests); + if (activity instanceof PreferenceActivity) { PreferenceActivity preferenceActivity = (PreferenceActivity) activity; // Only show the master switch when we're not in multi-pane mode, and not being used as diff --git a/src/com/android/settings/location/RecentLocationApps.java b/src/com/android/settings/location/RecentLocationApps.java new file mode 100644 index 00000000000..113928f948c --- /dev/null +++ b/src/com/android/settings/location/RecentLocationApps.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2013 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.location; + +import android.app.AppOpsManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.preference.PreferenceCategory; +import android.preference.PreferenceManager; +import android.preference.PreferenceScreen; +import android.util.Log; + +import com.android.settings.R; + +import java.util.List; + +/** + * Retrieves the information of applications which accessed location recently. + */ +public class RecentLocationApps { + private static final String TAG = RecentLocationApps.class.getSimpleName(); + + private static final int RECENT_TIME_INTERVAL_MILLIS = 15 * 60 * 1000; + + private Context mContext; + PackageManager mPackageManager; + + public RecentLocationApps(Context context) { + mContext = context; + mPackageManager = context.getPackageManager(); + } + + /** + * Fills a list of applications which queried location recently within + * specified time. + */ + public void fillAppList(PreferenceCategory container) { + AppOpsManager aoManager = + (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + List appOps = aoManager.getPackagesForOps( + new int[] { + AppOpsManager.OP_MONITOR_LOCATION, + AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, + }); + PreferenceManager preferenceManager = container.getPreferenceManager(); + long now = System.currentTimeMillis(); + for (AppOpsManager.PackageOps ops : appOps) { + processPackageOps(now, container, preferenceManager, ops); + } + } + + private void processPackageOps( + long now, + PreferenceCategory container, + PreferenceManager preferenceManager, + AppOpsManager.PackageOps ops) { + String packageName = ops.getPackageName(); + List entries = ops.getOps(); + boolean highBattery = false; + boolean normalBattery = false; + for (AppOpsManager.OpEntry entry : entries) { + // If previous location activity is older than designated interval, ignore this app. + if (now - entry.getTime() <= RECENT_TIME_INTERVAL_MILLIS) { + switch (entry.getOp()) { + case AppOpsManager.OP_MONITOR_LOCATION: + normalBattery = true; + break; + case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION: + highBattery = true; + break; + default: + break; + } + } + } + + if (!highBattery && !normalBattery) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, packageName + " hadn't used location within the time interval."); + } + return; + } + + try { + PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); + ApplicationInfo appInfo = mPackageManager.getApplicationInfo( + packageName, PackageManager.GET_META_DATA); + screen.setIcon(mPackageManager.getApplicationIcon(appInfo)); + screen.setTitle(mPackageManager.getApplicationLabel(appInfo)); + // if used both high and low battery within the time interval, show as "high + // battery" + if (highBattery) { + screen.setSummary(R.string.location_high_battery_use); + } else { + screen.setSummary(R.string.location_low_battery_use); + } + container.addPreference(screen); + } catch (PackageManager.NameNotFoundException e) { + // ignore the current app and move on to the next. + } + } +}