App ops: improve presentation.
Change-Id: Ia8702f9421a2cf2e27e8e24bfdc596321ace515a
This commit is contained in:
@@ -561,10 +561,28 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- User display names for app ops codes -->
|
<!-- User display names for app ops codes -->
|
||||||
<string-array name="app_ops_names">
|
<string-array name="app_ops_summaries">
|
||||||
<item>Coarse location</item>
|
<item>coarse location</item>
|
||||||
<item>Fine location</item>
|
<item>fine location</item>
|
||||||
<item>GPS</item>
|
<item>GPS</item>
|
||||||
|
<item>vibrate</item>
|
||||||
|
<item>read contacts</item>
|
||||||
|
<item>write contacts</item>
|
||||||
|
<item>read calls</item>
|
||||||
|
<item>write calls</item>
|
||||||
|
<item>read calendar</item>
|
||||||
|
<item>write calendar</item>
|
||||||
|
<item>wi-fi scan</item>
|
||||||
|
<item>notification</item>
|
||||||
|
<item>cell scan</item>
|
||||||
|
<item>call phone</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<!-- User display names for app ops codes -->
|
||||||
|
<string-array name="app_ops_labels">
|
||||||
|
<item>Location</item>
|
||||||
|
<item>Location</item>
|
||||||
|
<item>Location</item>
|
||||||
<item>Vibrate</item>
|
<item>Vibrate</item>
|
||||||
<item>Read contacts</item>
|
<item>Read contacts</item>
|
||||||
<item>Write contacts</item>
|
<item>Write contacts</item>
|
||||||
@@ -572,9 +590,9 @@
|
|||||||
<item>Write calls</item>
|
<item>Write calls</item>
|
||||||
<item>Read calendar</item>
|
<item>Read calendar</item>
|
||||||
<item>Write calendar</item>
|
<item>Write calendar</item>
|
||||||
<item>Wi-Fi scan</item>
|
<item>Location</item>
|
||||||
<item>Post notification</item>
|
<item>Post notification</item>
|
||||||
<item>Cell tower scan</item>
|
<item>Location</item>
|
||||||
<item>Call phone</item>
|
<item>Call phone</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
@@ -29,7 +29,6 @@ import android.content.res.Configuration;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -259,6 +258,17 @@ public class AppOpsCategory extends ListFragment implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasStableIds() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
// XXX need to generate real id.
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populate new items in the list.
|
* Populate new items in the list.
|
||||||
*/
|
*/
|
||||||
@@ -275,8 +285,9 @@ public class AppOpsCategory extends ListFragment implements
|
|||||||
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(
|
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(
|
||||||
item.getAppEntry().getIcon());
|
item.getAppEntry().getIcon());
|
||||||
((TextView)view.findViewById(R.id.app_name)).setText(item.getAppEntry().getLabel());
|
((TextView)view.findViewById(R.id.app_name)).setText(item.getAppEntry().getLabel());
|
||||||
((TextView)view.findViewById(R.id.op_name)).setText(item.getLabelText(mState));
|
((TextView)view.findViewById(R.id.op_name)).setText(item.getSummaryText(mState));
|
||||||
((TextView)view.findViewById(R.id.op_time)).setText(item.getTimeText(mResources));
|
((TextView)view.findViewById(R.id.op_time)).setText(
|
||||||
|
item.getTimeText(mResources, false));
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@@ -137,9 +137,9 @@ public class AppOpsDetails extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
((TextView)view.findViewById(R.id.op_name)).setText(
|
((TextView)view.findViewById(R.id.op_name)).setText(
|
||||||
entry.getBriefLabelText(mState));
|
entry.getSwitchText(mState));
|
||||||
((TextView)view.findViewById(R.id.op_time)).setText(
|
((TextView)view.findViewById(R.id.op_time)).setText(
|
||||||
entry.getTimeText(res));
|
entry.getTimeText(res, true));
|
||||||
Switch sw = (Switch)view.findViewById(R.id.switchWidget);
|
Switch sw = (Switch)view.findViewById(R.id.switchWidget);
|
||||||
final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
|
final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
|
||||||
sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
|
sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
|
||||||
|
@@ -47,7 +47,8 @@ public class AppOpsState {
|
|||||||
final Context mContext;
|
final Context mContext;
|
||||||
final AppOpsManager mAppOps;
|
final AppOpsManager mAppOps;
|
||||||
final PackageManager mPm;
|
final PackageManager mPm;
|
||||||
final CharSequence[] mOpNames;
|
final CharSequence[] mOpSummaries;
|
||||||
|
final CharSequence[] mOpLabels;
|
||||||
|
|
||||||
List<AppOpEntry> mApps;
|
List<AppOpEntry> mApps;
|
||||||
|
|
||||||
@@ -55,7 +56,8 @@ public class AppOpsState {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
|
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
mPm = context.getPackageManager();
|
mPm = context.getPackageManager();
|
||||||
mOpNames = context.getResources().getTextArray(R.array.app_ops_names);
|
mOpSummaries = context.getResources().getTextArray(R.array.app_ops_summaries);
|
||||||
|
mOpLabels = context.getResources().getTextArray(R.array.app_ops_labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class OpsTemplate implements Parcelable {
|
public static class OpsTemplate implements Parcelable {
|
||||||
@@ -226,19 +228,16 @@ public class AppOpsState {
|
|||||||
private final AppOpsManager.PackageOps mPkgOps;
|
private final AppOpsManager.PackageOps mPkgOps;
|
||||||
private final ArrayList<AppOpsManager.OpEntry> mOps
|
private final ArrayList<AppOpsManager.OpEntry> mOps
|
||||||
= new ArrayList<AppOpsManager.OpEntry>();
|
= new ArrayList<AppOpsManager.OpEntry>();
|
||||||
private final ArrayList<AppOpsManager.OpEntry> mBriefOps
|
private final ArrayList<AppOpsManager.OpEntry> mSwitchOps
|
||||||
= new ArrayList<AppOpsManager.OpEntry>();
|
= new ArrayList<AppOpsManager.OpEntry>();
|
||||||
private final AppEntry mApp;
|
private final AppEntry mApp;
|
||||||
|
|
||||||
public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app,
|
public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app) {
|
||||||
boolean brief) {
|
|
||||||
mPkgOps = pkg;
|
mPkgOps = pkg;
|
||||||
mApp = app;
|
mApp = app;
|
||||||
mApp.addOp(this, op);
|
mApp.addOp(this, op);
|
||||||
mOps.add(op);
|
mOps.add(op);
|
||||||
if (brief) {
|
mSwitchOps.add(op);
|
||||||
mBriefOps.add(op);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addOp(ArrayList<AppOpsManager.OpEntry> list, AppOpsManager.OpEntry op) {
|
private static void addOp(ArrayList<AppOpsManager.OpEntry> list, AppOpsManager.OpEntry op) {
|
||||||
@@ -259,11 +258,11 @@ public class AppOpsState {
|
|||||||
list.add(op);
|
list.add(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOp(AppOpsManager.OpEntry op, boolean brief) {
|
public void addOp(AppOpsManager.OpEntry op) {
|
||||||
mApp.addOp(this, op);
|
mApp.addOp(this, op);
|
||||||
addOp(mOps, op);
|
addOp(mOps, op);
|
||||||
if (brief) {
|
if (mApp.getOpSwitch(AppOpsManager.opToSwitch(op.getOp())) == null) {
|
||||||
addOp(mBriefOps, op);
|
addOp(mSwitchOps, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,35 +282,35 @@ public class AppOpsState {
|
|||||||
return mOps.get(pos);
|
return mOps.get(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CharSequence getLabelText(ArrayList<AppOpsManager.OpEntry> ops,
|
private CharSequence getCombinedText(ArrayList<AppOpsManager.OpEntry> ops,
|
||||||
AppOpsState state) {
|
CharSequence[] items) {
|
||||||
if (ops.size() == 1) {
|
if (ops.size() == 1) {
|
||||||
return state.mOpNames[ops.get(0).getOp()];
|
return items[ops.get(0).getOp()];
|
||||||
} else {
|
} else {
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (int i=0; i<ops.size(); i++) {
|
for (int i=0; i<ops.size(); i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
builder.append(", ");
|
builder.append(", ");
|
||||||
}
|
}
|
||||||
builder.append(state.mOpNames[ops.get(i).getOp()]);
|
builder.append(items[ops.get(i).getOp()]);
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getLabelText(AppOpsState state) {
|
public CharSequence getSummaryText(AppOpsState state) {
|
||||||
return getLabelText(mOps, state);
|
return getCombinedText(mOps, state.mOpSummaries);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getBriefLabelText(AppOpsState state) {
|
public CharSequence getSwitchText(AppOpsState state) {
|
||||||
if (mBriefOps.size() > 0) {
|
if (mSwitchOps.size() > 0) {
|
||||||
return getLabelText(mBriefOps, state);
|
return getCombinedText(mSwitchOps, state.mOpLabels);
|
||||||
} else {
|
} else {
|
||||||
return getLabelText(mOps, state);
|
return getCombinedText(mOps, state.mOpLabels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getTimeText(Resources res) {
|
public CharSequence getTimeText(Resources res, boolean showEmptyText) {
|
||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
return res.getText(R.string.app_ops_running);
|
return res.getText(R.string.app_ops_running);
|
||||||
}
|
}
|
||||||
@@ -321,7 +320,7 @@ public class AppOpsState {
|
|||||||
DateUtils.MINUTE_IN_MILLIS,
|
DateUtils.MINUTE_IN_MILLIS,
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE);
|
DateUtils.FORMAT_ABBREV_RELATIVE);
|
||||||
}
|
}
|
||||||
return "";
|
return showEmptyText ? res.getText(R.string.app_ops_never_used) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
@@ -358,7 +357,7 @@ public class AppOpsState {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private void addOp(List<AppOpEntry> entries, AppOpsManager.PackageOps pkgOps,
|
private void addOp(List<AppOpEntry> entries, AppOpsManager.PackageOps pkgOps,
|
||||||
AppEntry appEntry, AppOpsManager.OpEntry opEntry, boolean brief, boolean allowMerge) {
|
AppEntry appEntry, AppOpsManager.OpEntry opEntry, boolean allowMerge) {
|
||||||
if (allowMerge && entries.size() > 0) {
|
if (allowMerge && entries.size() > 0) {
|
||||||
AppOpEntry last = entries.get(entries.size()-1);
|
AppOpEntry last = entries.get(entries.size()-1);
|
||||||
if (last.getAppEntry() == appEntry) {
|
if (last.getAppEntry() == appEntry) {
|
||||||
@@ -367,17 +366,17 @@ public class AppOpsState {
|
|||||||
if (lastExe == entryExe) {
|
if (lastExe == entryExe) {
|
||||||
if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
|
if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
|
||||||
+ pkgOps.getPackageName() + ": append to " + last);
|
+ pkgOps.getPackageName() + ": append to " + last);
|
||||||
last.addOp(opEntry, brief);
|
last.addOp(opEntry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AppOpEntry entry = appEntry.getOpSwitch(opEntry.getOp());
|
AppOpEntry entry = appEntry.getOpSwitch(opEntry.getOp());
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
entry.addOp(opEntry, brief);
|
entry.addOp(opEntry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
entry = new AppOpEntry(pkgOps, opEntry, appEntry, brief);
|
entry = new AppOpEntry(pkgOps, opEntry, appEntry);
|
||||||
if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
|
if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
|
||||||
+ pkgOps.getPackageName() + ": making new " + entry);
|
+ pkgOps.getPackageName() + ": making new " + entry);
|
||||||
entries.add(entry);
|
entries.add(entry);
|
||||||
@@ -416,9 +415,7 @@ public class AppOpsState {
|
|||||||
|
|
||||||
final ArrayList<String> perms = new ArrayList<String>();
|
final ArrayList<String> perms = new ArrayList<String>();
|
||||||
final ArrayList<Integer> permOps = new ArrayList<Integer>();
|
final ArrayList<Integer> permOps = new ArrayList<Integer>();
|
||||||
final boolean[] brief = new boolean[AppOpsManager._NUM_OP];
|
|
||||||
for (int i=0; i<tpl.ops.length; i++) {
|
for (int i=0; i<tpl.ops.length; i++) {
|
||||||
brief[tpl.ops[i]] = tpl.showPerms[i];
|
|
||||||
if (tpl.showPerms[i]) {
|
if (tpl.showPerms[i]) {
|
||||||
String perm = AppOpsManager.opToPermission(tpl.ops[i]);
|
String perm = AppOpsManager.opToPermission(tpl.ops[i]);
|
||||||
if (perm != null && !perms.contains(perm)) {
|
if (perm != null && !perms.contains(perm)) {
|
||||||
@@ -444,8 +441,7 @@ public class AppOpsState {
|
|||||||
}
|
}
|
||||||
for (int j=0; j<pkgOps.getOps().size(); j++) {
|
for (int j=0; j<pkgOps.getOps().size(); j++) {
|
||||||
AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(j);
|
AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(j);
|
||||||
addOp(entries, pkgOps, appEntry, opEntry, brief[opEntry.getOp()],
|
addOp(entries, pkgOps, appEntry, opEntry, packageName == null);
|
||||||
packageName == null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -502,8 +498,7 @@ public class AppOpsState {
|
|||||||
AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
|
AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
|
||||||
permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0);
|
permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0);
|
||||||
dummyOps.add(opEntry);
|
dummyOps.add(opEntry);
|
||||||
addOp(entries, pkgOps, appEntry, opEntry, brief[opEntry.getOp()],
|
addOp(entries, pkgOps, appEntry, opEntry, packageName == null);
|
||||||
packageName == null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,22 +510,4 @@ public class AppOpsState {
|
|||||||
// Done!
|
// Done!
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CharSequence getLabelText(AppOpsManager.OpEntry op) {
|
|
||||||
return mOpNames[op.getOp()];
|
|
||||||
}
|
|
||||||
|
|
||||||
public CharSequence getTimeText(AppOpsManager.OpEntry op) {
|
|
||||||
if (op.isRunning()) {
|
|
||||||
return mContext.getResources().getText(R.string.app_ops_running);
|
|
||||||
}
|
|
||||||
if (op.getTime() > 0) {
|
|
||||||
return DateUtils.getRelativeTimeSpanString(op.getTime(),
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
DateUtils.MINUTE_IN_MILLIS,
|
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE);
|
|
||||||
}
|
|
||||||
return mContext.getResources().getText(R.string.app_ops_never_used);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user