Merge "Work on issue #78480444: Start tracking uid state in app ops" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
55c2d4106a
@@ -109,6 +109,27 @@ public class AppOpsManager {
|
||||
*/
|
||||
public static final int MODE_DEFAULT = 3;
|
||||
|
||||
/**
|
||||
* Special mode that means "allow only when app is in foreground." This is <b>not</b>
|
||||
* returned from {@link #checkOp}, {@link #noteOp}, {@link #startOp}; rather, when this
|
||||
* mode is set, these functions will return {@link #MODE_ALLOWED} when the app being
|
||||
* checked is currently in the foreground, otherwise {@link #MODE_IGNORED}.
|
||||
* @hide
|
||||
*/
|
||||
public static final int MODE_FOREGROUND = 4;
|
||||
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static final String[] MODE_NAMES = new String[] {
|
||||
"allow", // MODE_ALLOWED
|
||||
"ignore", // MODE_IGNORED
|
||||
"deny", // MODE_ERRORED
|
||||
"default", // MODE_DEFAULT
|
||||
"foreground", // MODE_FOREGROUND
|
||||
};
|
||||
|
||||
/**
|
||||
* Metrics about an op when its uid is persistent.
|
||||
* @hide
|
||||
@@ -619,83 +640,83 @@ public class AppOpsManager {
|
||||
* make them all controlled by the same single operation.
|
||||
*/
|
||||
private static int[] sOpToSwitch = new int[] {
|
||||
OP_COARSE_LOCATION,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_VIBRATE,
|
||||
OP_READ_CONTACTS,
|
||||
OP_WRITE_CONTACTS,
|
||||
OP_READ_CALL_LOG,
|
||||
OP_WRITE_CALL_LOG,
|
||||
OP_READ_CALENDAR,
|
||||
OP_WRITE_CALENDAR,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_POST_NOTIFICATION,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_CALL_PHONE,
|
||||
OP_READ_SMS,
|
||||
OP_WRITE_SMS,
|
||||
OP_RECEIVE_SMS,
|
||||
OP_RECEIVE_SMS,
|
||||
OP_RECEIVE_MMS,
|
||||
OP_RECEIVE_WAP_PUSH,
|
||||
OP_SEND_SMS,
|
||||
OP_READ_SMS,
|
||||
OP_WRITE_SMS,
|
||||
OP_WRITE_SETTINGS,
|
||||
OP_SYSTEM_ALERT_WINDOW,
|
||||
OP_ACCESS_NOTIFICATIONS,
|
||||
OP_CAMERA,
|
||||
OP_RECORD_AUDIO,
|
||||
OP_PLAY_AUDIO,
|
||||
OP_READ_CLIPBOARD,
|
||||
OP_WRITE_CLIPBOARD,
|
||||
OP_TAKE_MEDIA_BUTTONS,
|
||||
OP_TAKE_AUDIO_FOCUS,
|
||||
OP_AUDIO_MASTER_VOLUME,
|
||||
OP_AUDIO_VOICE_VOLUME,
|
||||
OP_AUDIO_RING_VOLUME,
|
||||
OP_AUDIO_MEDIA_VOLUME,
|
||||
OP_AUDIO_ALARM_VOLUME,
|
||||
OP_AUDIO_NOTIFICATION_VOLUME,
|
||||
OP_AUDIO_BLUETOOTH_VOLUME,
|
||||
OP_WAKE_LOCK,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_COARSE_LOCATION,
|
||||
OP_GET_USAGE_STATS,
|
||||
OP_MUTE_MICROPHONE,
|
||||
OP_TOAST_WINDOW,
|
||||
OP_PROJECT_MEDIA,
|
||||
OP_ACTIVATE_VPN,
|
||||
OP_WRITE_WALLPAPER,
|
||||
OP_ASSIST_STRUCTURE,
|
||||
OP_ASSIST_SCREENSHOT,
|
||||
OP_READ_PHONE_STATE,
|
||||
OP_ADD_VOICEMAIL,
|
||||
OP_USE_SIP,
|
||||
OP_PROCESS_OUTGOING_CALLS,
|
||||
OP_USE_FINGERPRINT,
|
||||
OP_BODY_SENSORS,
|
||||
OP_READ_CELL_BROADCASTS,
|
||||
OP_MOCK_LOCATION,
|
||||
OP_READ_EXTERNAL_STORAGE,
|
||||
OP_WRITE_EXTERNAL_STORAGE,
|
||||
OP_TURN_SCREEN_ON,
|
||||
OP_GET_ACCOUNTS,
|
||||
OP_RUN_IN_BACKGROUND,
|
||||
OP_AUDIO_ACCESSIBILITY_VOLUME,
|
||||
OP_READ_PHONE_NUMBERS,
|
||||
OP_REQUEST_INSTALL_PACKAGES,
|
||||
OP_PICTURE_IN_PICTURE,
|
||||
OP_INSTANT_APP_START_FOREGROUND,
|
||||
OP_ANSWER_PHONE_CALLS,
|
||||
OP_RUN_ANY_IN_BACKGROUND,
|
||||
OP_CHANGE_WIFI_STATE,
|
||||
OP_REQUEST_DELETE_PACKAGES,
|
||||
OP_BIND_ACCESSIBILITY_SERVICE,
|
||||
OP_ACCEPT_HANDOVER,
|
||||
OP_MANAGE_IPSEC_TUNNELS,
|
||||
OP_START_FOREGROUND,
|
||||
OP_COARSE_LOCATION, // COARSE_LOCATION
|
||||
OP_COARSE_LOCATION, // FINE_LOCATION
|
||||
OP_COARSE_LOCATION, // GPS
|
||||
OP_VIBRATE, // VIBRATE
|
||||
OP_READ_CONTACTS, // READ_CONTACTS
|
||||
OP_WRITE_CONTACTS, // WRITE_CONTACTS
|
||||
OP_READ_CALL_LOG, // READ_CALL_LOG
|
||||
OP_WRITE_CALL_LOG, // WRITE_CALL_LOG
|
||||
OP_READ_CALENDAR, // READ_CALENDAR
|
||||
OP_WRITE_CALENDAR, // WRITE_CALENDAR
|
||||
OP_COARSE_LOCATION, // WIFI_SCAN
|
||||
OP_POST_NOTIFICATION, // POST_NOTIFICATION
|
||||
OP_COARSE_LOCATION, // NEIGHBORING_CELLS
|
||||
OP_CALL_PHONE, // CALL_PHONE
|
||||
OP_READ_SMS, // READ_SMS
|
||||
OP_WRITE_SMS, // WRITE_SMS
|
||||
OP_RECEIVE_SMS, // RECEIVE_SMS
|
||||
OP_RECEIVE_SMS, // RECEIVE_EMERGECY_SMS
|
||||
OP_RECEIVE_MMS, // RECEIVE_MMS
|
||||
OP_RECEIVE_WAP_PUSH, // RECEIVE_WAP_PUSH
|
||||
OP_SEND_SMS, // SEND_SMS
|
||||
OP_READ_SMS, // READ_ICC_SMS
|
||||
OP_WRITE_SMS, // WRITE_ICC_SMS
|
||||
OP_WRITE_SETTINGS, // WRITE_SETTINGS
|
||||
OP_SYSTEM_ALERT_WINDOW, // SYSTEM_ALERT_WINDOW
|
||||
OP_ACCESS_NOTIFICATIONS, // ACCESS_NOTIFICATIONS
|
||||
OP_CAMERA, // CAMERA
|
||||
OP_RECORD_AUDIO, // RECORD_AUDIO
|
||||
OP_PLAY_AUDIO, // PLAY_AUDIO
|
||||
OP_READ_CLIPBOARD, // READ_CLIPBOARD
|
||||
OP_WRITE_CLIPBOARD, // WRITE_CLIPBOARD
|
||||
OP_TAKE_MEDIA_BUTTONS, // TAKE_MEDIA_BUTTONS
|
||||
OP_TAKE_AUDIO_FOCUS, // TAKE_AUDIO_FOCUS
|
||||
OP_AUDIO_MASTER_VOLUME, // AUDIO_MASTER_VOLUME
|
||||
OP_AUDIO_VOICE_VOLUME, // AUDIO_VOICE_VOLUME
|
||||
OP_AUDIO_RING_VOLUME, // AUDIO_RING_VOLUME
|
||||
OP_AUDIO_MEDIA_VOLUME, // AUDIO_MEDIA_VOLUME
|
||||
OP_AUDIO_ALARM_VOLUME, // AUDIO_ALARM_VOLUME
|
||||
OP_AUDIO_NOTIFICATION_VOLUME, // AUDIO_NOTIFICATION_VOLUME
|
||||
OP_AUDIO_BLUETOOTH_VOLUME, // AUDIO_BLUETOOTH_VOLUME
|
||||
OP_WAKE_LOCK, // WAKE_LOCK
|
||||
OP_COARSE_LOCATION, // MONITOR_LOCATION
|
||||
OP_COARSE_LOCATION, // MONITOR_HIGH_POWER_LOCATION
|
||||
OP_GET_USAGE_STATS, // GET_USAGE_STATS
|
||||
OP_MUTE_MICROPHONE, // MUTE_MICROPHONE
|
||||
OP_TOAST_WINDOW, // TOAST_WINDOW
|
||||
OP_PROJECT_MEDIA, // PROJECT_MEDIA
|
||||
OP_ACTIVATE_VPN, // ACTIVATE_VPN
|
||||
OP_WRITE_WALLPAPER, // WRITE_WALLPAPER
|
||||
OP_ASSIST_STRUCTURE, // ASSIST_STRUCTURE
|
||||
OP_ASSIST_SCREENSHOT, // ASSIST_SCREENSHOT
|
||||
OP_READ_PHONE_STATE, // READ_PHONE_STATE
|
||||
OP_ADD_VOICEMAIL, // ADD_VOICEMAIL
|
||||
OP_USE_SIP, // USE_SIP
|
||||
OP_PROCESS_OUTGOING_CALLS, // PROCESS_OUTGOING_CALLS
|
||||
OP_USE_FINGERPRINT, // USE_FINGERPRINT
|
||||
OP_BODY_SENSORS, // BODY_SENSORS
|
||||
OP_READ_CELL_BROADCASTS, // READ_CELL_BROADCASTS
|
||||
OP_MOCK_LOCATION, // MOCK_LOCATION
|
||||
OP_READ_EXTERNAL_STORAGE, // READ_EXTERNAL_STORAGE
|
||||
OP_WRITE_EXTERNAL_STORAGE, // WRITE_EXTERNAL_STORAGE
|
||||
OP_TURN_SCREEN_ON, // TURN_SCREEN_ON
|
||||
OP_GET_ACCOUNTS, // GET_ACCOUNTS
|
||||
OP_RUN_IN_BACKGROUND, // RUN_IN_BACKGROUND
|
||||
OP_AUDIO_ACCESSIBILITY_VOLUME, // AUDIO_ACCESSIBILITY_VOLUME
|
||||
OP_READ_PHONE_NUMBERS, // READ_PHONE_NUMBERS
|
||||
OP_REQUEST_INSTALL_PACKAGES, // REQUEST_INSTALL_PACKAGES
|
||||
OP_PICTURE_IN_PICTURE, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
|
||||
OP_INSTANT_APP_START_FOREGROUND, // INSTANT_APP_START_FOREGROUND
|
||||
OP_ANSWER_PHONE_CALLS, // ANSWER_PHONE_CALLS
|
||||
OP_RUN_ANY_IN_BACKGROUND, // OP_RUN_ANY_IN_BACKGROUND
|
||||
OP_CHANGE_WIFI_STATE, // OP_CHANGE_WIFI_STATE
|
||||
OP_REQUEST_DELETE_PACKAGES, // OP_REQUEST_DELETE_PACKAGES
|
||||
OP_BIND_ACCESSIBILITY_SERVICE, // OP_BIND_ACCESSIBILITY_SERVICE
|
||||
OP_ACCEPT_HANDOVER, // ACCEPT_HANDOVER
|
||||
OP_MANAGE_IPSEC_TUNNELS, // MANAGE_IPSEC_HANDOVERS
|
||||
OP_START_FOREGROUND, // START_FOREGROUND
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1420,19 +1441,11 @@ public class AppOpsManager {
|
||||
* Retrieve the human readable mode.
|
||||
* @hide
|
||||
*/
|
||||
public static String modeToString(int mode) {
|
||||
switch (mode) {
|
||||
case MODE_ALLOWED:
|
||||
return "allow";
|
||||
case MODE_IGNORED:
|
||||
return "ignore";
|
||||
case MODE_ERRORED:
|
||||
return "deny";
|
||||
case MODE_DEFAULT:
|
||||
return "default";
|
||||
default:
|
||||
return "mode=" + mode;
|
||||
public static String modeToName(int mode) {
|
||||
if (mode >= 0 && mode < MODE_NAMES.length) {
|
||||
return MODE_NAMES[mode];
|
||||
}
|
||||
return "mode=" + mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1554,30 +1567,42 @@ public class AppOpsManager {
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
long time = 0;
|
||||
for (int i = 0; i < _NUM_UID_STATE; i++) {
|
||||
if (mTimes[i] > time) {
|
||||
time = mTimes[i];
|
||||
}
|
||||
}
|
||||
return time;
|
||||
return maxTime(mTimes, 0, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getTimeFor(int uidState) {
|
||||
public long getLastAccessTime() {
|
||||
return maxTime(mTimes, 0, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getLastAccessForegroundTime() {
|
||||
return maxTime(mTimes, UID_STATE_PERSISTENT, UID_STATE_FOREGROUND_SERVICE + 1);
|
||||
}
|
||||
|
||||
public long getLastAccessBackgroundTime() {
|
||||
return maxTime(mTimes, UID_STATE_FOREGROUND_SERVICE + 1, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getLastTimeFor(int uidState) {
|
||||
return mTimes[uidState];
|
||||
}
|
||||
|
||||
public long getRejectTime() {
|
||||
long time = 0;
|
||||
for (int i = 0; i < _NUM_UID_STATE; i++) {
|
||||
if (mRejectTimes[i] > time) {
|
||||
time = mRejectTimes[i];
|
||||
}
|
||||
}
|
||||
return time;
|
||||
return maxTime(mRejectTimes, 0, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getRejectTimeFor(int uidState) {
|
||||
public long getLastRejectTime() {
|
||||
return maxTime(mRejectTimes, 0, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getLastRejectForegroundTime() {
|
||||
return maxTime(mRejectTimes, UID_STATE_PERSISTENT, UID_STATE_FOREGROUND_SERVICE + 1);
|
||||
}
|
||||
|
||||
public long getLastRejectBackgroundTime() {
|
||||
return maxTime(mRejectTimes, UID_STATE_FOREGROUND_SERVICE + 1, _NUM_UID_STATE);
|
||||
}
|
||||
|
||||
public long getLastRejectTimeFor(int uidState) {
|
||||
return mRejectTimes[uidState];
|
||||
}
|
||||
|
||||
@@ -1680,6 +1705,7 @@ public class AppOpsManager {
|
||||
* @param ops The set of operations you are interested in, or null if you want all of them.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
|
||||
public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
|
||||
try {
|
||||
return mService.getPackagesForOps(ops);
|
||||
@@ -1696,6 +1722,7 @@ public class AppOpsManager {
|
||||
* @param ops The set of operations you are interested in, or null if you want all of them.
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
|
||||
public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, int[] ops) {
|
||||
try {
|
||||
return mService.getOpsForPackage(uid, packageName, ops);
|
||||
@@ -2009,6 +2036,17 @@ public class AppOpsManager {
|
||||
* used for a quick check to see if an operation has been disabled for the application,
|
||||
* as an early reject of some work. This does not modify the time stamp or other data
|
||||
* about the operation.
|
||||
*
|
||||
* <p>Important things this will not do (which you need to ultimate use
|
||||
* {@link #noteOp(String, int, String)} or {@link #startOp(String, int, String)} to cover):</p>
|
||||
* <ul>
|
||||
* <li>Verifying the uid and package are consistent, so callers can't spoof
|
||||
* their identity.</li>
|
||||
* <li>Taking into account the current foreground/background state of the
|
||||
* app; apps whose mode varies by this state will always be reported
|
||||
* as {@link #MODE_ALLOWED}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param op The operation to check. One of the OPSTR_* constants.
|
||||
* @param uid The user id of the application attempting to perform the operation.
|
||||
* @param packageName The name of the application attempting to perform the operation.
|
||||
@@ -2128,6 +2166,17 @@ public class AppOpsManager {
|
||||
* used for a quick check to see if an operation has been disabled for the application,
|
||||
* as an early reject of some work. This does not modify the time stamp or other data
|
||||
* about the operation.
|
||||
*
|
||||
* <p>Important things this will not do (which you need to ultimate use
|
||||
* {@link #noteOp(int, int, String)} or {@link #startOp(int, int, String)} to cover):</p>
|
||||
* <ul>
|
||||
* <li>Verifying the uid and package are consistent, so callers can't spoof
|
||||
* their identity.</li>
|
||||
* <li>Taking into account the current foreground/background state of the
|
||||
* app; apps whose mode varies by this state will always be reported
|
||||
* as {@link #MODE_ALLOWED}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param op The operation to check. One of the OP_* constants.
|
||||
* @param uid The user id of the application attempting to perform the operation.
|
||||
* @param packageName The name of the application attempting to perform the operation.
|
||||
@@ -2445,4 +2494,17 @@ public class AppOpsManager {
|
||||
public static String[] getOpStrs() {
|
||||
return Arrays.copyOf(sOpToString, sOpToString.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static long maxTime(long[] times, int start, int end) {
|
||||
long time = 0;
|
||||
for (int i = start; i < end; i++) {
|
||||
if (times[i] > time) {
|
||||
time = times[i];
|
||||
}
|
||||
}
|
||||
return time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TimeUtils;
|
||||
import android.util.Xml;
|
||||
@@ -108,6 +109,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// Write at most every 30 minutes.
|
||||
static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
|
||||
|
||||
// How long we want for a drop in uid state to settle before applying it.
|
||||
static final long STATE_SETTLE_TIME = 10*1000;
|
||||
|
||||
// Constant meaning that any UID should be matched when dispatching callbacks
|
||||
private static final int UID_ANY = -2;
|
||||
|
||||
@@ -162,13 +166,6 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
"rc", // UID_STATE_CACHED
|
||||
};
|
||||
|
||||
static final String[] MODE_NAMES = new String[] {
|
||||
"allow", // MODE_ALLOWED
|
||||
"ignore", // MODE_IGNORED
|
||||
"deny", // MODE_ERRORED
|
||||
"default", // MODE_DEFAULT
|
||||
};
|
||||
|
||||
Context mContext;
|
||||
final AtomicFile mFile;
|
||||
final Handler mHandler;
|
||||
@@ -194,6 +191,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
@VisibleForTesting
|
||||
final SparseArray<UidState> mUidStates = new SparseArray<>();
|
||||
|
||||
long mLastUptime;
|
||||
|
||||
/*
|
||||
* These are app op restrictions imposed per user from various parties.
|
||||
*/
|
||||
@@ -202,11 +201,17 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
@VisibleForTesting
|
||||
static final class UidState {
|
||||
public final int uid;
|
||||
|
||||
public int state = UID_STATE_CACHED;
|
||||
public int pendingState = UID_STATE_CACHED;
|
||||
public long pendingStateCommitTime;
|
||||
|
||||
public int startNesting;
|
||||
public ArrayMap<String, Ops> pkgOps;
|
||||
public SparseIntArray opModes;
|
||||
|
||||
public SparseBooleanArray foregroundOps;
|
||||
|
||||
public UidState(int uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
@@ -220,6 +225,32 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return (pkgOps == null || pkgOps.isEmpty())
|
||||
&& (opModes == null || opModes.size() <= 0);
|
||||
}
|
||||
|
||||
int evalMode(int mode) {
|
||||
if (mode == AppOpsManager.MODE_FOREGROUND) {
|
||||
return state <= UID_STATE_FOREGROUND_SERVICE
|
||||
? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void evalForegroundOps() {
|
||||
SparseBooleanArray which = null;
|
||||
if (pkgOps != null) {
|
||||
for (int i = pkgOps.size() - 1; i >= 0; i--) {
|
||||
Ops ops = pkgOps.valueAt(i);
|
||||
for (int j = ops.size() - 1; j >= 0; j--) {
|
||||
if (ops.valueAt(j).mode == AppOpsManager.MODE_FOREGROUND) {
|
||||
if (which == null) {
|
||||
which = new SparseBooleanArray();
|
||||
}
|
||||
which.put(ops.keyAt(j), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foregroundOps = which;
|
||||
}
|
||||
}
|
||||
|
||||
final static class Ops extends SparseArray<Op> {
|
||||
@@ -267,6 +298,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int getMode() {
|
||||
return uidState.evalMode(mode);
|
||||
}
|
||||
}
|
||||
|
||||
final SparseArray<ArraySet<ModeCallback>> mOpModeWatchers = new SparseArray<>();
|
||||
@@ -575,7 +610,16 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
synchronized (this) {
|
||||
final UidState uidState = getUidStateLocked(uid, true);
|
||||
final int newState = PROCESS_STATE_TO_UID_STATE[procState];
|
||||
if (uidState != null && uidState.state != newState) {
|
||||
if (uidState != null && uidState.pendingState != newState) {
|
||||
if (newState < uidState.state) {
|
||||
// We are moving to a more important state, always do it immediately.
|
||||
uidState.state = newState;
|
||||
uidState.pendingStateCommitTime = 0;
|
||||
} else if (uidState.pendingStateCommitTime == 0) {
|
||||
// We are moving to a less important state for the first time,
|
||||
// delay the application for a bit.
|
||||
uidState.pendingStateCommitTime = SystemClock.uptimeMillis() + STATE_SETTLE_TIME;
|
||||
}
|
||||
if (uidState.startNesting != 0) {
|
||||
// There is some actively running operation... need to find it
|
||||
// and appropriately update its state.
|
||||
@@ -585,13 +629,13 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
for (int j = ops.size() - 1; j >= 0; j--) {
|
||||
final Op op = ops.valueAt(j);
|
||||
if (op.startNesting > 0) {
|
||||
op.time[uidState.state] = now;
|
||||
op.time[uidState.pendingState] = now;
|
||||
op.time[newState] = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
uidState.state = newState;
|
||||
uidState.pendingState = newState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -887,6 +931,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (op != null) {
|
||||
if (op.mode != mode) {
|
||||
op.mode = mode;
|
||||
if (uidState != null) {
|
||||
uidState.evalForegroundOps();
|
||||
}
|
||||
ArraySet<ModeCallback> cbs = mOpModeWatchers.get(code);
|
||||
if (cbs != null) {
|
||||
if (repCbs == null) {
|
||||
@@ -1046,6 +1093,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
|
||||
Map<String, Ops> packages = uidState.pkgOps;
|
||||
Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
|
||||
boolean uidChanged = false;
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, Ops> ent = it.next();
|
||||
String packageName = ent.getKey();
|
||||
@@ -1060,6 +1108,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
&& curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
|
||||
curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
|
||||
changed = true;
|
||||
uidChanged = true;
|
||||
callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
|
||||
mOpModeWatchers.get(curOp.op));
|
||||
callbacks = addCallbacks(callbacks, curOp.op, curOp.uid, packageName,
|
||||
@@ -1076,6 +1125,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (uidState.isDefault()) {
|
||||
mUidStates.remove(uidState.uid);
|
||||
}
|
||||
if (uidChanged) {
|
||||
uidState.evalForegroundOps();
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@@ -1197,7 +1249,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (op == null) {
|
||||
return AppOpsManager.opToDefaultMode(code);
|
||||
}
|
||||
return op.mode;
|
||||
return op.mode == AppOpsManager.MODE_FOREGROUND ? AppOpsManager.MODE_ALLOWED : op.mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1352,9 +1404,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// If there is a non-default per UID policy (we set UID op mode only if
|
||||
// non-default) it takes over, otherwise use the per package policy.
|
||||
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
|
||||
final int uidMode = uidState.opModes.get(switchCode);
|
||||
final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode));
|
||||
if (uidMode != AppOpsManager.MODE_ALLOWED) {
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
|
||||
+ switchCode + " (" + code + ") uid " + uid + " package "
|
||||
+ packageName);
|
||||
op.rejectTime[uidState.state] = System.currentTimeMillis();
|
||||
@@ -1362,12 +1414,13 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
} else {
|
||||
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
|
||||
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
|
||||
final int mode = switchOp.getMode();
|
||||
if (mode != AppOpsManager.MODE_ALLOWED) {
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
|
||||
+ switchCode + " (" + code + ") uid " + uid + " package "
|
||||
+ packageName);
|
||||
op.rejectTime[uidState.state] = System.currentTimeMillis();
|
||||
return switchOp.mode;
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
|
||||
@@ -1458,10 +1511,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
// If there is a non-default per UID policy (we set UID op mode only if
|
||||
// non-default) it takes over, otherwise use the per package policy.
|
||||
if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
|
||||
final int uidMode = uidState.opModes.get(switchCode);
|
||||
final int uidMode = uidState.evalMode(uidState.opModes.get(switchCode));
|
||||
if (uidMode != AppOpsManager.MODE_ALLOWED
|
||||
&& (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + op.mode + " for code "
|
||||
if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
|
||||
+ switchCode + " (" + code + ") uid " + uid + " package "
|
||||
+ resolvedPackageName);
|
||||
op.rejectTime[uidState.state] = System.currentTimeMillis();
|
||||
@@ -1469,13 +1522,14 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
} else {
|
||||
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
|
||||
if (switchOp.mode != AppOpsManager.MODE_ALLOWED
|
||||
&& (!startIfModeDefault || switchOp.mode != AppOpsManager.MODE_DEFAULT)) {
|
||||
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + op.mode + " for code "
|
||||
final int mode = switchOp.getMode();
|
||||
if (mode != AppOpsManager.MODE_ALLOWED
|
||||
&& (!startIfModeDefault || mode != AppOpsManager.MODE_DEFAULT)) {
|
||||
if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
|
||||
+ switchCode + " (" + code + ") uid " + uid + " package "
|
||||
+ resolvedPackageName);
|
||||
op.rejectTime[uidState.state] = System.currentTimeMillis();
|
||||
return switchOp.mode;
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
|
||||
@@ -1642,6 +1696,19 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
uidState = new UidState(uid);
|
||||
mUidStates.put(uid, uidState);
|
||||
} else {
|
||||
if (uidState.pendingStateCommitTime != 0) {
|
||||
if (uidState.pendingStateCommitTime < mLastUptime) {
|
||||
uidState.state = uidState.pendingState;
|
||||
uidState.pendingStateCommitTime = 0;
|
||||
} else {
|
||||
mLastUptime = SystemClock.uptimeMillis();
|
||||
if (uidState.pendingStateCommitTime < mLastUptime) {
|
||||
uidState.state = uidState.pendingState;
|
||||
uidState.pendingStateCommitTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uidState;
|
||||
}
|
||||
@@ -1870,6 +1937,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (uidState.pkgOps == null) {
|
||||
continue;
|
||||
}
|
||||
boolean changed = false;
|
||||
for (int j = 0; j < uidState.pkgOps.size(); j++) {
|
||||
Ops ops = uidState.pkgOps.valueAt(j);
|
||||
if (ops != null) {
|
||||
@@ -1879,9 +1947,13 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
|
||||
copy.mode = op.mode;
|
||||
ops.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, copy);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
uidState.evalForegroundOps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2077,6 +2149,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
}
|
||||
}
|
||||
UidState uidState = getUidStateLocked(uid, false);
|
||||
if (uidState != null) {
|
||||
uidState.evalForegroundOps();
|
||||
}
|
||||
}
|
||||
|
||||
void writeState() {
|
||||
@@ -2152,12 +2228,12 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
out.attribute(null, "m", Integer.toString(op.getMode()));
|
||||
}
|
||||
for (int k = 0; k < _NUM_UID_STATE; k++) {
|
||||
final long time = op.getTimeFor(k);
|
||||
final long time = op.getLastTimeFor(k);
|
||||
if (time != 0) {
|
||||
out.attribute(null, UID_STATE_TIME_ATTRS[k],
|
||||
Long.toString(time));
|
||||
}
|
||||
final long rejectTime = op.getRejectTimeFor(k);
|
||||
final long rejectTime = op.getLastRejectTimeFor(k);
|
||||
if (rejectTime != 0) {
|
||||
out.attribute(null, UID_STATE_REJECT_ATTRS[k],
|
||||
Long.toString(rejectTime));
|
||||
@@ -2229,7 +2305,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
dumpCommandHelp(pw);
|
||||
}
|
||||
|
||||
private int strOpToOp(String op, PrintWriter err) {
|
||||
static private int strOpToOp(String op, PrintWriter err) {
|
||||
try {
|
||||
return AppOpsManager.strOpToOp(op);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@@ -2247,8 +2323,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
|
||||
int strModeToMode(String modeStr, PrintWriter err) {
|
||||
for (int i = MODE_NAMES.length - 1; i >= 0; i--) {
|
||||
if (MODE_NAMES[i].equals(modeStr)) {
|
||||
for (int i = AppOpsManager.MODE_NAMES.length - 1; i >= 0; i--) {
|
||||
if (AppOpsManager.MODE_NAMES[i].equals(modeStr)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -2470,7 +2546,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
if (ops == null || ops.size() <= 0) {
|
||||
pw.println("No operations.");
|
||||
if (shell.op > AppOpsManager.OP_NONE && shell.op < AppOpsManager._NUM_OP) {
|
||||
pw.println("Default mode: " + AppOpsManager.modeToString(
|
||||
pw.println("Default mode: " + AppOpsManager.modeToName(
|
||||
AppOpsManager.opToDefaultMode(shell.op)));
|
||||
}
|
||||
return 0;
|
||||
@@ -2482,7 +2558,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
AppOpsManager.OpEntry ent = entries.get(j);
|
||||
pw.print(AppOpsManager.opToName(ent.getOp()));
|
||||
pw.print(": ");
|
||||
pw.print(AppOpsManager.modeToString(ent.getMode()));
|
||||
pw.print(AppOpsManager.modeToName(ent.getMode()));
|
||||
if (ent.getTime() != 0) {
|
||||
pw.print("; time=");
|
||||
TimeUtils.formatDuration(now - ent.getTime(), pw);
|
||||
@@ -2636,7 +2712,10 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
|
||||
private void dumpHelp(PrintWriter pw) {
|
||||
pw.println("AppOps service (appops) dump options:");
|
||||
pw.println(" none");
|
||||
pw.println(" -h");
|
||||
pw.println(" Print this help text.");
|
||||
pw.println(" --op [OP]");
|
||||
pw.println(" Limit output to data associated with the given app op code.");
|
||||
}
|
||||
|
||||
private void dumpTimesLocked(PrintWriter pw, String firstPrefix, String prefix, long[] times,
|
||||
@@ -2671,6 +2750,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
|
||||
|
||||
int dumpOp = -1;
|
||||
|
||||
if (args != null) {
|
||||
for (int i=0; i<args.length; i++) {
|
||||
String arg = args[i];
|
||||
@@ -2679,6 +2760,16 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
return;
|
||||
} else if ("-a".equals(arg)) {
|
||||
// dump all data
|
||||
} else if ("--op".equals(arg)) {
|
||||
i++;
|
||||
if (i >= args.length) {
|
||||
pw.println("No argument for --op option");
|
||||
return;
|
||||
}
|
||||
dumpOp = Shell.strOpToOp(args[i], pw);
|
||||
if (dumpOp < 0) {
|
||||
return;
|
||||
}
|
||||
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
|
||||
pw.println("Unknown option: " + arg);
|
||||
return;
|
||||
@@ -2693,13 +2784,21 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
pw.println("Current AppOps Service state:");
|
||||
final long now = System.currentTimeMillis();
|
||||
final long nowElapsed = SystemClock.elapsedRealtime();
|
||||
final long nowUptime = SystemClock.uptimeMillis();
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
final Date date = new Date();
|
||||
boolean needSep = false;
|
||||
if (mOpModeWatchers.size() > 0) {
|
||||
needSep = true;
|
||||
pw.println(" Op mode watchers:");
|
||||
boolean printedHeader = false;
|
||||
for (int i=0; i<mOpModeWatchers.size(); i++) {
|
||||
if (dumpOp >= 0 && dumpOp != mOpModeWatchers.keyAt(i)) {
|
||||
continue;
|
||||
}
|
||||
if (!printedHeader) {
|
||||
pw.println(" Op mode watchers:");
|
||||
printedHeader = true;
|
||||
}
|
||||
pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
|
||||
pw.println(":");
|
||||
ArraySet<ModeCallback> callbacks = mOpModeWatchers.valueAt(i);
|
||||
@@ -2722,7 +2821,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mModeWatchers.size() > 0) {
|
||||
if (mModeWatchers.size() > 0 && dumpOp < 0) {
|
||||
needSep = true;
|
||||
pw.println(" All op mode watchers:");
|
||||
for (int i=0; i<mModeWatchers.size(); i++) {
|
||||
@@ -2733,12 +2832,19 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
if (mActiveWatchers.size() > 0) {
|
||||
needSep = true;
|
||||
pw.println(" All op active watchers:");
|
||||
boolean printedHeader = false;
|
||||
for (int i = 0; i < mActiveWatchers.size(); i++) {
|
||||
final SparseArray<ActiveCallback> activeWatchers = mActiveWatchers.valueAt(i);
|
||||
if (activeWatchers.size() <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (dumpOp >= 0 && activeWatchers.indexOfKey(dumpOp) < 0) {
|
||||
continue;
|
||||
}
|
||||
if (!printedHeader) {
|
||||
pw.println(" All op active watchers:");
|
||||
printedHeader = true;
|
||||
}
|
||||
pw.print(" ");
|
||||
pw.print(Integer.toHexString(System.identityHashCode(
|
||||
mActiveWatchers.keyAt(i))));
|
||||
@@ -2746,6 +2852,9 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
pw.print(" [");
|
||||
final int opCount = activeWatchers.size();
|
||||
for (i = 0; i < opCount; i++) {
|
||||
if (i > 0) {
|
||||
pw.print(' ');
|
||||
}
|
||||
pw.print(AppOpsManager.opToName(activeWatchers.keyAt(i)));
|
||||
if (i < opCount - 1) {
|
||||
pw.print(',');
|
||||
@@ -2758,15 +2867,30 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
if (mClients.size() > 0) {
|
||||
needSep = true;
|
||||
pw.println(" Clients:");
|
||||
boolean printedHeader = false;
|
||||
for (int i=0; i<mClients.size(); i++) {
|
||||
pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":");
|
||||
boolean printedClient = false;
|
||||
ClientState cs = mClients.valueAt(i);
|
||||
pw.print(" "); pw.println(cs);
|
||||
if (cs.mStartedOps.size() > 0) {
|
||||
pw.println(" Started ops:");
|
||||
boolean printedStarted = false;
|
||||
for (int j=0; j<cs.mStartedOps.size(); j++) {
|
||||
Op op = cs.mStartedOps.get(j);
|
||||
if (dumpOp >= 0 && op.op != dumpOp) {
|
||||
continue;
|
||||
}
|
||||
if (!printedHeader) {
|
||||
pw.println(" Clients:");
|
||||
printedHeader = true;
|
||||
}
|
||||
if (!printedClient) {
|
||||
pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":");
|
||||
pw.print(" "); pw.println(cs);
|
||||
printedClient = true;
|
||||
}
|
||||
if (!printedStarted) {
|
||||
pw.println(" Started ops:");
|
||||
printedStarted = true;
|
||||
}
|
||||
pw.print(" "); pw.print("uid="); pw.print(op.uid);
|
||||
pw.print(" pkg="); pw.print(op.packageName);
|
||||
pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
|
||||
@@ -2774,7 +2898,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mAudioRestrictions.size() > 0) {
|
||||
if (mAudioRestrictions.size() > 0 && dumpOp < 0) {
|
||||
boolean printedHeader = false;
|
||||
for (int o=0; o<mAudioRestrictions.size(); o++) {
|
||||
final String op = AppOpsManager.opToName(mAudioRestrictions.keyAt(o));
|
||||
@@ -2789,7 +2913,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
pw.print(" "); pw.print(op);
|
||||
pw.print(" usage="); pw.print(AudioAttributes.usageToString(usage));
|
||||
Restriction r = restrictions.valueAt(i);
|
||||
pw.print(": mode="); pw.println(MODE_NAMES[r.mode]);
|
||||
pw.print(": mode="); pw.println(AppOpsManager.modeToName(r.mode));
|
||||
if (!r.exceptionPackages.isEmpty()) {
|
||||
pw.println(" Exceptions:");
|
||||
for (int j=0; j<r.exceptionPackages.size(); j++) {
|
||||
@@ -2804,38 +2928,83 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
for (int i=0; i<mUidStates.size(); i++) {
|
||||
UidState uidState = mUidStates.valueAt(i);
|
||||
final SparseIntArray opModes = uidState.opModes;
|
||||
final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
|
||||
|
||||
if (dumpOp >= 0) {
|
||||
boolean hasOp = uidState.opModes != null
|
||||
&& uidState.opModes.indexOfKey(dumpOp) >= 0;
|
||||
if (pkgOps != null) {
|
||||
for (int pkgi = 0; !hasOp && pkgi < pkgOps.size(); pkgi++) {
|
||||
Ops ops = pkgOps.valueAt(pkgi);
|
||||
if (ops != null && ops.indexOfKey(dumpOp) >= 0) {
|
||||
hasOp = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasOp) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
pw.print(" Uid "); UserHandle.formatUid(pw, uidState.uid); pw.println(":");
|
||||
pw.print(" state=");
|
||||
pw.println(UID_STATE_NAMES[uidState.state]);
|
||||
if (uidState.state != uidState.pendingState) {
|
||||
pw.print(" pendingState=");
|
||||
pw.println(UID_STATE_NAMES[uidState.pendingState]);
|
||||
}
|
||||
if (uidState.pendingStateCommitTime != 0) {
|
||||
pw.print(" pendingStateCommitTime=");
|
||||
TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowUptime, pw);
|
||||
pw.println();
|
||||
}
|
||||
if (uidState.startNesting != 0) {
|
||||
pw.print(" startNesting=");
|
||||
pw.println(uidState.startNesting);
|
||||
}
|
||||
if (uidState.foregroundOps != null) {
|
||||
pw.println(" foregroundOps:");
|
||||
for (int j = 0; j < uidState.foregroundOps.size(); j++) {
|
||||
pw.print(" ");
|
||||
pw.println(AppOpsManager.opToName(uidState.foregroundOps.keyAt(j)));
|
||||
}
|
||||
}
|
||||
needSep = true;
|
||||
|
||||
SparseIntArray opModes = uidState.opModes;
|
||||
if (opModes != null) {
|
||||
final int opModeCount = opModes.size();
|
||||
for (int j = 0; j < opModeCount; j++) {
|
||||
final int code = opModes.keyAt(j);
|
||||
final int mode = opModes.valueAt(j);
|
||||
if (dumpOp >= 0 && dumpOp != code) {
|
||||
continue;
|
||||
}
|
||||
pw.print(" "); pw.print(AppOpsManager.opToName(code));
|
||||
pw.print(": mode="); pw.println(MODE_NAMES[mode]);
|
||||
pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
|
||||
}
|
||||
}
|
||||
|
||||
ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
|
||||
if (pkgOps == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Ops ops : pkgOps.values()) {
|
||||
pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
|
||||
for (int pkgi = 0; pkgi < pkgOps.size(); pkgi++) {
|
||||
Ops ops = pkgOps.valueAt(pkgi);
|
||||
boolean printedPackage = false;
|
||||
for (int j=0; j<ops.size(); j++) {
|
||||
Op op = ops.valueAt(j);
|
||||
if (dumpOp >= 0 && dumpOp != op.op) {
|
||||
continue;
|
||||
}
|
||||
if (!printedPackage) {
|
||||
pw.print(" Package "); pw.print(ops.packageName); pw.println(":");
|
||||
printedPackage = true;
|
||||
}
|
||||
pw.print(" "); pw.print(AppOpsManager.opToName(op.op));
|
||||
pw.print(" ("); pw.print(MODE_NAMES[op.mode]); pw.println("): ");
|
||||
pw.print(" ("); pw.print(AppOpsManager.modeToName(op.mode));
|
||||
pw.println("): ");
|
||||
dumpTimesLocked(pw,
|
||||
" Access: ",
|
||||
" ", op.time, now, sdf, date);
|
||||
|
||||
Reference in New Issue
Block a user