App ops: improve presentation.

Change-Id: Ia8702f9421a2cf2e27e8e24bfdc596321ace515a
This commit is contained in:
Dianne Hackborn
2013-02-01 17:29:15 -08:00
parent 27daaab633
commit 8b0afc7fb5
4 changed files with 68 additions and 62 deletions

View File

@@ -561,10 +561,28 @@
</string-array>
<!-- User display names for app ops codes -->
<string-array name="app_ops_names">
<item>Coarse location</item>
<item>Fine location</item>
<string-array name="app_ops_summaries">
<item>coarse location</item>
<item>fine location</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>Read contacts</item>
<item>Write contacts</item>
@@ -572,12 +590,12 @@
<item>Write calls</item>
<item>Read calendar</item>
<item>Write calendar</item>
<item>Wi-Fi scan</item>
<item>Location</item>
<item>Post notification</item>
<item>Cell tower scan</item>
<item>Location</item>
<item>Call phone</item>
</string-array>
<!-- Titles for the list of long press timeout options. -->
<string-array name="long_press_timeout_selector_titles">
<!-- A title for the option for short long-press timeout [CHAR LIMIT=25] -->

View File

@@ -29,7 +29,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
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.
*/
@@ -275,8 +285,9 @@ public class AppOpsCategory extends ListFragment implements
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(
item.getAppEntry().getIcon());
((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_time)).setText(item.getTimeText(mResources));
((TextView)view.findViewById(R.id.op_name)).setText(item.getSummaryText(mState));
((TextView)view.findViewById(R.id.op_time)).setText(
item.getTimeText(mResources, false));
return view;
}

View File

@@ -137,9 +137,9 @@ public class AppOpsDetails extends Fragment {
}
}
((TextView)view.findViewById(R.id.op_name)).setText(
entry.getBriefLabelText(mState));
entry.getSwitchText(mState));
((TextView)view.findViewById(R.id.op_time)).setText(
entry.getTimeText(res));
entry.getTimeText(res, true));
Switch sw = (Switch)view.findViewById(R.id.switchWidget);
final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),

View File

@@ -47,7 +47,8 @@ public class AppOpsState {
final Context mContext;
final AppOpsManager mAppOps;
final PackageManager mPm;
final CharSequence[] mOpNames;
final CharSequence[] mOpSummaries;
final CharSequence[] mOpLabels;
List<AppOpEntry> mApps;
@@ -55,7 +56,8 @@ public class AppOpsState {
mContext = context;
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
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 {
@@ -226,19 +228,16 @@ public class AppOpsState {
private final AppOpsManager.PackageOps mPkgOps;
private final ArrayList<AppOpsManager.OpEntry> mOps
= new ArrayList<AppOpsManager.OpEntry>();
private final ArrayList<AppOpsManager.OpEntry> mBriefOps
private final ArrayList<AppOpsManager.OpEntry> mSwitchOps
= new ArrayList<AppOpsManager.OpEntry>();
private final AppEntry mApp;
public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app,
boolean brief) {
public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app) {
mPkgOps = pkg;
mApp = app;
mApp.addOp(this, op);
mOps.add(op);
if (brief) {
mBriefOps.add(op);
}
mSwitchOps.add(op);
}
private static void addOp(ArrayList<AppOpsManager.OpEntry> list, AppOpsManager.OpEntry op) {
@@ -259,11 +258,11 @@ public class AppOpsState {
list.add(op);
}
public void addOp(AppOpsManager.OpEntry op, boolean brief) {
public void addOp(AppOpsManager.OpEntry op) {
mApp.addOp(this, op);
addOp(mOps, op);
if (brief) {
addOp(mBriefOps, op);
if (mApp.getOpSwitch(AppOpsManager.opToSwitch(op.getOp())) == null) {
addOp(mSwitchOps, op);
}
}
@@ -283,35 +282,35 @@ public class AppOpsState {
return mOps.get(pos);
}
private CharSequence getLabelText(ArrayList<AppOpsManager.OpEntry> ops,
AppOpsState state) {
private CharSequence getCombinedText(ArrayList<AppOpsManager.OpEntry> ops,
CharSequence[] items) {
if (ops.size() == 1) {
return state.mOpNames[ops.get(0).getOp()];
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(state.mOpNames[ops.get(i).getOp()]);
builder.append(items[ops.get(i).getOp()]);
}
return builder.toString();
}
}
public CharSequence getLabelText(AppOpsState state) {
return getLabelText(mOps, state);
public CharSequence getSummaryText(AppOpsState state) {
return getCombinedText(mOps, state.mOpSummaries);
}
public CharSequence getBriefLabelText(AppOpsState state) {
if (mBriefOps.size() > 0) {
return getLabelText(mBriefOps, state);
public CharSequence getSwitchText(AppOpsState state) {
if (mSwitchOps.size() > 0) {
return getCombinedText(mSwitchOps, state.mOpLabels);
} else {
return getLabelText(mOps, state);
return getCombinedText(mOps, state.mOpLabels);
}
}
public CharSequence getTimeText(Resources res) {
public CharSequence getTimeText(Resources res, boolean showEmptyText) {
if (isRunning()) {
return res.getText(R.string.app_ops_running);
}
@@ -321,7 +320,7 @@ public class AppOpsState {
DateUtils.MINUTE_IN_MILLIS,
DateUtils.FORMAT_ABBREV_RELATIVE);
}
return "";
return showEmptyText ? res.getText(R.string.app_ops_never_used) : "";
}
public boolean isRunning() {
@@ -358,7 +357,7 @@ public class AppOpsState {
};
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) {
AppOpEntry last = entries.get(entries.size()-1);
if (last.getAppEntry() == appEntry) {
@@ -367,17 +366,17 @@ public class AppOpsState {
if (lastExe == entryExe) {
if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
+ pkgOps.getPackageName() + ": append to " + last);
last.addOp(opEntry, brief);
last.addOp(opEntry);
return;
}
}
}
AppOpEntry entry = appEntry.getOpSwitch(opEntry.getOp());
if (entry != null) {
entry.addOp(opEntry, brief);
entry.addOp(opEntry);
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 "
+ pkgOps.getPackageName() + ": making new " + entry);
entries.add(entry);
@@ -416,9 +415,7 @@ public class AppOpsState {
final ArrayList<String> perms = new ArrayList<String>();
final ArrayList<Integer> permOps = new ArrayList<Integer>();
final boolean[] brief = new boolean[AppOpsManager._NUM_OP];
for (int i=0; i<tpl.ops.length; i++) {
brief[tpl.ops[i]] = tpl.showPerms[i];
if (tpl.showPerms[i]) {
String perm = AppOpsManager.opToPermission(tpl.ops[i]);
if (perm != null && !perms.contains(perm)) {
@@ -444,8 +441,7 @@ public class AppOpsState {
}
for (int j=0; j<pkgOps.getOps().size(); j++) {
AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(j);
addOp(entries, pkgOps, appEntry, opEntry, brief[opEntry.getOp()],
packageName == null);
addOp(entries, pkgOps, appEntry, opEntry, packageName == null);
}
}
}
@@ -502,8 +498,7 @@ public class AppOpsState {
AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0);
dummyOps.add(opEntry);
addOp(entries, pkgOps, appEntry, opEntry, brief[opEntry.getOp()],
packageName == null);
addOp(entries, pkgOps, appEntry, opEntry, packageName == null);
}
}
}
@@ -515,22 +510,4 @@ public class AppOpsState {
// Done!
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);
}
}