summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings')
-rw-r--r--src/com/android/settings/applications/AppOpsDetails.java2
-rw-r--r--src/com/android/settings/applications/AppOpsState.java117
-rw-r--r--src/com/android/settings/applications/AppOpsSummary.java114
3 files changed, 202 insertions, 31 deletions
diff --git a/src/com/android/settings/applications/AppOpsDetails.java b/src/com/android/settings/applications/AppOpsDetails.java
index 13e4831..12da8b8 100644
--- a/src/com/android/settings/applications/AppOpsDetails.java
+++ b/src/com/android/settings/applications/AppOpsDetails.java
@@ -172,6 +172,8 @@ public class AppOpsDetails extends InstrumentedFragment {
}
((TextView)view.findViewById(R.id.op_name)).setText(
entry.getSwitchText(mState));
+ ((TextView)view.findViewById(R.id.op_counts)).setText(
+ entry.getCountsText(res));
((TextView)view.findViewById(R.id.op_time)).setText(
entry.getTimeText(res, true));
diff --git a/src/com/android/settings/applications/AppOpsState.java b/src/com/android/settings/applications/AppOpsState.java
index ae58ddd..e46d94a 100644
--- a/src/com/android/settings/applications/AppOpsState.java
+++ b/src/com/android/settings/applications/AppOpsState.java
@@ -16,6 +16,7 @@
package com.android.settings.applications;
+import android.app.Activity;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -23,6 +24,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -52,12 +54,15 @@ public class AppOpsState {
List<AppOpEntry> mApps;
+ private SharedPreferences mPreferences;
+
public AppOpsState(Context context) {
mContext = context;
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mPm = context.getPackageManager();
mOpSummaries = context.getResources().getTextArray(R.array.app_ops_summaries_cm);
mOpLabels = context.getResources().getTextArray(R.array.app_ops_labels_cm);
+ mPreferences = context.getSharedPreferences("appops_manager", Activity.MODE_PRIVATE);
}
public static class OpsTemplate implements Parcelable {
@@ -383,30 +388,59 @@ public class AppOpsState {
}
private CharSequence getCombinedText(ArrayList<AppOpsManager.OpEntry> ops,
- CharSequence[] items) {
- if (ops.size() == 1) {
- return items[ops.get(0).getOp()];
- } else {
- StringBuilder builder = new StringBuilder();
- for (int i=0; i<ops.size(); i++) {
- if (i > 0) {
- builder.append(", ");
- }
- builder.append(items[ops.get(i).getOp()]);
+ CharSequence[] items, Resources res, boolean withTerseCounts) {
+ StringBuilder builder = new StringBuilder();
+ for (int i=0; i<ops.size(); i++) {
+ if (i > 0) {
+ builder.append(", ");
}
- return builder.toString();
+ AppOpsManager.OpEntry op = ops.get(i);
+ int count = op.getAllowedCount() + op.getIgnoredCount();
+
+ if (withTerseCounts && count > 0) {
+ String quantity = res.getQuantityString(R.plurals.app_ops_count,
+ count, count);
+ builder.append(res.getString(R.string.app_ops_entry_summary,
+ items[op.getOp()], quantity));
+ } else {
+ builder.append(items[op.getOp()]);
+ }
+ }
+ return builder.toString();
+ }
+
+ public CharSequence getCountsText(Resources res) {
+ AppOpsManager.OpEntry op = mOps.get(0);
+ int allowed = op.getAllowedCount();
+ int denied = op.getIgnoredCount();
+
+ if (allowed == 0 && denied == 0) {
+ return null;
}
+
+ CharSequence allowedQuantity = res.getQuantityString(R.plurals.app_ops_count,
+ allowed, allowed);
+ CharSequence deniedQuantity = res.getQuantityString(R.plurals.app_ops_count,
+ denied, denied);
+
+ if (denied == 0) {
+ return res.getString(R.string.app_ops_allowed_count, allowedQuantity);
+ } else if (allowed == 0) {
+ return res.getString(R.string.app_ops_ignored_count, deniedQuantity);
+ }
+ return res.getString(R.string.app_ops_both_count, allowedQuantity, deniedQuantity);
}
public CharSequence getSummaryText(AppOpsState state) {
- return getCombinedText(mOps, state.mOpSummaries);
+ return getCombinedText(mOps, state.mOpSummaries, state.mContext.getResources(), true);
}
public CharSequence getSwitchText(AppOpsState state) {
+ final Resources res = state.mContext.getResources();
if (mSwitchOps.size() > 0) {
- return getCombinedText(mSwitchOps, state.mOpLabels);
+ return getCombinedText(mSwitchOps, state.mOpLabels, res, false);
} else {
- return getCombinedText(mOps, state.mOpLabels);
+ return getCombinedText(mOps, state.mOpLabels, res, false);
}
}
@@ -490,19 +524,34 @@ public class AppOpsState {
}
private AppEntry getAppEntry(final Context context, final HashMap<String, AppEntry> appEntries,
- final String packageName, ApplicationInfo appInfo) {
+ final String packageName, ApplicationInfo appInfo, boolean applyFilters) {
+
+ if (appInfo == null) {
+ try {
+ appInfo = mPm.getApplicationInfo(packageName,
+ PackageManager.GET_DISABLED_COMPONENTS
+ | PackageManager.GET_UNINSTALLED_PACKAGES);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to find info for package " + packageName);
+ return null;
+ }
+ }
+
+ if (applyFilters) {
+ // Hide user apps if needed
+ if (!shouldShowUserApps() &&
+ (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+ return null;
+ }
+ // Hide system apps if needed
+ if (!shouldShowSystemApps() &&
+ (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ return null;
+ }
+ }
+
AppEntry appEntry = appEntries.get(packageName);
if (appEntry == null) {
- if (appInfo == null) {
- try {
- appInfo = mPm.getApplicationInfo(packageName,
- PackageManager.GET_DISABLED_COMPONENTS
- | PackageManager.GET_UNINSTALLED_PACKAGES);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Unable to find info for package " + packageName);
- return null;
- }
- }
appEntry = new AppEntry(this, appInfo);
appEntry.loadLabel(context);
appEntries.put(packageName, appEntry);
@@ -510,6 +559,14 @@ public class AppOpsState {
return appEntry;
}
+ private boolean shouldShowUserApps() {
+ return mPreferences.getBoolean("show_user_apps", true);
+ }
+
+ private boolean shouldShowSystemApps() {
+ return mPreferences.getBoolean("show_system_apps", true);
+ }
+
public List<AppOpEntry> buildState(OpsTemplate tpl, int uid, String packageName) {
final Context context = mContext;
@@ -530,6 +587,9 @@ public class AppOpsState {
}
}
+ // Whether to apply hide user / system app filters
+ final boolean applyFilters = (packageName == null);
+
List<AppOpsManager.PackageOps> pkgs;
if (packageName != null) {
pkgs = mAppOps.getOpsForPackage(uid, packageName, tpl.ops);
@@ -540,7 +600,8 @@ public class AppOpsState {
if (pkgs != null) {
for (int i=0; i<pkgs.size(); i++) {
AppOpsManager.PackageOps pkgOps = pkgs.get(i);
- AppEntry appEntry = getAppEntry(context, appEntries, pkgOps.getPackageName(), null);
+ AppEntry appEntry = getAppEntry(context, appEntries, pkgOps.getPackageName(), null,
+ applyFilters);
if (appEntry == null) {
continue;
}
@@ -568,7 +629,7 @@ public class AppOpsState {
for (int i=0; i<apps.size(); i++) {
PackageInfo appInfo = apps.get(i);
AppEntry appEntry = getAppEntry(context, appEntries, appInfo.packageName,
- appInfo.applicationInfo);
+ appInfo.applicationInfo, applyFilters);
if (appEntry == null) {
continue;
}
@@ -602,7 +663,7 @@ public class AppOpsState {
}
AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
- permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0, -1, null);
+ permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0, -1, null, 0, 0);
dummyOps.add(opEntry);
addOp(entries, pkgOps, appEntry, opEntry, packageName == null,
packageName == null ? 0 : opToOrder[opEntry.getOp()]);
diff --git a/src/com/android/settings/applications/AppOpsSummary.java b/src/com/android/settings/applications/AppOpsSummary.java
index 0d47dc1..71af7f4 100644
--- a/src/com/android/settings/applications/AppOpsSummary.java
+++ b/src/com/android/settings/applications/AppOpsSummary.java
@@ -16,10 +16,16 @@
package com.android.settings.applications;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.AppOpsManager;
import android.app.Fragment;
import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceFrameLayout;
import android.support.v13.app.FragmentPagerAdapter;
@@ -27,6 +33,9 @@ import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
import android.util.TypedValue;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -42,6 +51,11 @@ public class AppOpsSummary extends InstrumentedFragment {
private View mRootView;
private ViewPager mViewPager;
+ private MyPagerAdapter mAdapter;
+
+ private Activity mActivity;
+ private SharedPreferences mPreferences;
+
CharSequence[] mPageNames;
static AppOpsState.OpsTemplate[] sPageTemplates = new AppOpsState.OpsTemplate[] {
AppOpsState.LOCATION_TEMPLATE,
@@ -88,6 +102,10 @@ public class AppOpsSummary extends InstrumentedFragment {
mCurPos = position;
}
+ public int getCurrentPage() {
+ return mCurPos;
+ }
+
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
@@ -96,6 +114,14 @@ public class AppOpsSummary extends InstrumentedFragment {
}
}
+ private void resetAdapter() {
+ // trigger adapter load, preserving the selected page
+ int curPos = mAdapter.getCurrentPage();
+ mViewPager.setAdapter(mAdapter);
+ mViewPager.setOnPageChangeListener(mAdapter);
+ mViewPager.setCurrentItem(curPos);
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// initialize the inflater
@@ -109,9 +135,9 @@ public class AppOpsSummary extends InstrumentedFragment {
mPageNames = getResources().getTextArray(R.array.app_ops_categories_cm);
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
- MyPagerAdapter adapter = new MyPagerAdapter(getChildFragmentManager());
- mViewPager.setAdapter(adapter);
- mViewPager.setOnPageChangeListener(adapter);
+ mAdapter = new MyPagerAdapter(getChildFragmentManager());
+ mViewPager.setAdapter(mAdapter);
+ mViewPager.setOnPageChangeListener(mAdapter);
PagerTabStrip tabs = (PagerTabStrip) rootView.findViewById(R.id.tabs);
Resources.Theme theme = tabs.getContext().getTheme();
@@ -126,6 +152,88 @@ public class AppOpsSummary extends InstrumentedFragment {
((PreferenceFrameLayout.LayoutParams) rootView.getLayoutParams()).removeBorders = true;
}
+ mActivity = getActivity();
+
return rootView;
}
+
+ private boolean shouldShowUserApps() {
+ return mPreferences.getBoolean("show_user_apps", true);
+ }
+
+ private boolean shouldShowSystemApps() {
+ return mPreferences.getBoolean("show_system_apps", true);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ // get shared preferences
+ mPreferences = mActivity.getSharedPreferences("appops_manager", Activity.MODE_PRIVATE);
+
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.appops_manager, menu);
+ menu.findItem(R.id.show_user_apps).setChecked(shouldShowUserApps());
+ menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps());
+ }
+
+ private void resetCounters() {
+ final AppOpsManager appOps =
+ (AppOpsManager) mActivity.getSystemService(Context.APP_OPS_SERVICE);
+ if (appOps == null) {
+ return;
+ }
+ appOps.resetCounters();
+ // reload content
+ resetAdapter();
+ }
+
+ private void resetCountersConfirm() {
+ new AlertDialog.Builder(getActivity())
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(R.string.app_ops_reset_confirm_title)
+ .setMessage(R.string.app_ops_reset_confirm_mesg)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
+ {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ resetCounters();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, null)
+ .show();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.show_user_apps:
+ final String prefNameUserApps = "show_user_apps";
+ // set the menu checkbox and save it in shared preference
+ item.setChecked(!item.isChecked());
+ mPreferences.edit().putBoolean(prefNameUserApps, item.isChecked()).commit();
+ // reload content
+ resetAdapter();
+ return true;
+ case R.id.show_system_apps:
+ final String prefNameSysApps = "show_system_apps";
+ // set the menu checkbox and save it in shared preference
+ item.setChecked(!item.isChecked());
+ mPreferences.edit().putBoolean(prefNameSysApps, item.isChecked()).commit();
+ // reload view content
+ resetAdapter();
+ return true;
+ case R.id.reset_counters:
+ resetCountersConfirm();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
}