diff options
Diffstat (limited to 'services/java/com/android/server/AppOpsService.java')
-rw-r--r-- | services/java/com/android/server/AppOpsService.java | 1083 |
1 files changed, 0 insertions, 1083 deletions
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java deleted file mode 100644 index a1a0d47..0000000 --- a/services/java/com/android/server/AppOpsService.java +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Copyright (C) 2012 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.server; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import android.app.AppOpsManager; -import android.content.Context; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.AsyncTask; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.util.ArrayMap; -import android.util.AtomicFile; -import android.util.Log; -import android.util.Pair; -import android.util.Slog; -import android.util.SparseArray; -import android.util.TimeUtils; -import android.util.Xml; - -import com.android.internal.app.IAppOpsService; -import com.android.internal.app.IAppOpsCallback; -import com.android.internal.util.FastXmlSerializer; -import com.android.internal.util.XmlUtils; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - -public class AppOpsService extends IAppOpsService.Stub { - static final String TAG = "AppOps"; - static final boolean DEBUG = false; - - // Write at most every 30 minutes. - static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; - - Context mContext; - final AtomicFile mFile; - final Handler mHandler; - - boolean mWriteScheduled; - final Runnable mWriteRunner = new Runnable() { - public void run() { - synchronized (AppOpsService.this) { - mWriteScheduled = false; - AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { - @Override protected Void doInBackground(Void... params) { - writeState(); - return null; - } - }; - task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); - } - } - }; - - final SparseArray<HashMap<String, Ops>> mUidOps - = new SparseArray<HashMap<String, Ops>>(); - - public final static class Ops extends SparseArray<Op> { - public final String packageName; - public final int uid; - - public Ops(String _packageName, int _uid) { - packageName = _packageName; - uid = _uid; - } - } - - public final static class Op { - public final int uid; - public final String packageName; - public final int op; - public int mode; - public int duration; - public long time; - public long rejectTime; - public int nesting; - - public Op(int _uid, String _packageName, int _op) { - uid = _uid; - packageName = _packageName; - op = _op; - mode = AppOpsManager.opToDefaultMode(op); - } - } - - final SparseArray<ArrayList<Callback>> mOpModeWatchers - = new SparseArray<ArrayList<Callback>>(); - final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers - = new ArrayMap<String, ArrayList<Callback>>(); - final ArrayMap<IBinder, Callback> mModeWatchers - = new ArrayMap<IBinder, Callback>(); - - public final class Callback implements DeathRecipient { - final IAppOpsCallback mCallback; - - public Callback(IAppOpsCallback callback) { - mCallback = callback; - try { - mCallback.asBinder().linkToDeath(this, 0); - } catch (RemoteException e) { - } - } - - public void unlinkToDeath() { - mCallback.asBinder().unlinkToDeath(this, 0); - } - - @Override - public void binderDied() { - stopWatchingMode(mCallback); - } - } - - final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>(); - - public final class ClientState extends Binder implements DeathRecipient { - final IBinder mAppToken; - final int mPid; - final ArrayList<Op> mStartedOps; - - public ClientState(IBinder appToken) { - mAppToken = appToken; - mPid = Binder.getCallingPid(); - if (appToken instanceof Binder) { - // For local clients, there is no reason to track them. - mStartedOps = null; - } else { - mStartedOps = new ArrayList<Op>(); - try { - mAppToken.linkToDeath(this, 0); - } catch (RemoteException e) { - } - } - } - - @Override - public String toString() { - return "ClientState{" + - "mAppToken=" + mAppToken + - ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") + - '}'; - } - - @Override - public void binderDied() { - synchronized (AppOpsService.this) { - for (int i=mStartedOps.size()-1; i>=0; i--) { - finishOperationLocked(mStartedOps.get(i)); - } - mClients.remove(mAppToken); - } - } - } - - public AppOpsService(File storagePath) { - mFile = new AtomicFile(storagePath); - mHandler = new Handler(); - readState(); - } - - public void publish(Context context) { - mContext = context; - ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); - } - - public void systemReady() { - synchronized (this) { - boolean changed = false; - for (int i=0; i<mUidOps.size(); i++) { - HashMap<String, Ops> pkgs = mUidOps.valueAt(i); - Iterator<Ops> it = pkgs.values().iterator(); - while (it.hasNext()) { - Ops ops = it.next(); - int curUid; - try { - curUid = mContext.getPackageManager().getPackageUid(ops.packageName, - UserHandle.getUserId(ops.uid)); - } catch (NameNotFoundException e) { - curUid = -1; - } - if (curUid != ops.uid) { - Slog.i(TAG, "Pruning old package " + ops.packageName - + "/" + ops.uid + ": new uid=" + curUid); - it.remove(); - changed = true; - } - } - if (pkgs.size() <= 0) { - mUidOps.removeAt(i); - } - } - if (changed) { - scheduleWriteLocked(); - } - } - } - - public void packageRemoved(int uid, String packageName) { - synchronized (this) { - HashMap<String, Ops> pkgs = mUidOps.get(uid); - if (pkgs != null) { - if (pkgs.remove(packageName) != null) { - if (pkgs.size() <= 0) { - mUidOps.remove(uid); - } - scheduleWriteLocked(); - } - } - } - } - - public void uidRemoved(int uid) { - synchronized (this) { - if (mUidOps.indexOfKey(uid) >= 0) { - mUidOps.remove(uid); - scheduleWriteLocked(); - } - } - } - - public void shutdown() { - Slog.w(TAG, "Writing app ops before shutdown..."); - boolean doWrite = false; - synchronized (this) { - if (mWriteScheduled) { - mWriteScheduled = false; - doWrite = true; - } - } - if (doWrite) { - writeState(); - } - } - - private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { - ArrayList<AppOpsManager.OpEntry> resOps = null; - if (ops == null) { - resOps = new ArrayList<AppOpsManager.OpEntry>(); - for (int j=0; j<pkgOps.size(); j++) { - Op curOp = pkgOps.valueAt(j); - resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, - curOp.rejectTime, curOp.duration)); - } - } else { - for (int j=0; j<ops.length; j++) { - Op curOp = pkgOps.get(ops[j]); - if (curOp != null) { - if (resOps == null) { - resOps = new ArrayList<AppOpsManager.OpEntry>(); - } - resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time, - curOp.rejectTime, curOp.duration)); - } - } - } - return resOps; - } - - @Override - public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { - mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, - Binder.getCallingPid(), Binder.getCallingUid(), null); - ArrayList<AppOpsManager.PackageOps> res = null; - synchronized (this) { - for (int i=0; i<mUidOps.size(); i++) { - HashMap<String, Ops> packages = mUidOps.valueAt(i); - for (Ops pkgOps : packages.values()) { - ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); - if (resOps != null) { - if (res == null) { - res = new ArrayList<AppOpsManager.PackageOps>(); - } - AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( - pkgOps.packageName, pkgOps.uid, resOps); - res.add(resPackage); - } - } - } - } - return res; - } - - @Override - public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, - int[] ops) { - mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, - Binder.getCallingPid(), Binder.getCallingUid(), null); - synchronized (this) { - Ops pkgOps = getOpsLocked(uid, packageName, false); - if (pkgOps == null) { - return null; - } - ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); - if (resOps == null) { - return null; - } - ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); - AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( - pkgOps.packageName, pkgOps.uid, resOps); - res.add(resPackage); - return res; - } - } - - private void pruneOp(Op op, int uid, String packageName) { - if (op.time == 0 && op.rejectTime == 0) { - Ops ops = getOpsLocked(uid, packageName, false); - if (ops != null) { - ops.remove(op.op); - if (ops.size() <= 0) { - HashMap<String, Ops> pkgOps = mUidOps.get(uid); - if (pkgOps != null) { - pkgOps.remove(ops.packageName); - if (pkgOps.size() <= 0) { - mUidOps.remove(uid); - } - } - } - } - } - } - - @Override - public void setMode(int code, int uid, String packageName, int mode) { - verifyIncomingUid(uid); - verifyIncomingOp(code); - ArrayList<Callback> repCbs = null; - code = AppOpsManager.opToSwitch(code); - synchronized (this) { - Op op = getOpLocked(code, uid, packageName, true); - if (op != null) { - if (op.mode != mode) { - op.mode = mode; - ArrayList<Callback> cbs = mOpModeWatchers.get(code); - if (cbs != null) { - if (repCbs == null) { - repCbs = new ArrayList<Callback>(); - } - repCbs.addAll(cbs); - } - cbs = mPackageModeWatchers.get(packageName); - if (cbs != null) { - if (repCbs == null) { - repCbs = new ArrayList<Callback>(); - } - repCbs.addAll(cbs); - } - if (mode == AppOpsManager.opToDefaultMode(op.op)) { - // If going into the default mode, prune this op - // if there is nothing else interesting in it. - pruneOp(op, uid, packageName); - } - scheduleWriteNowLocked(); - } - } - } - if (repCbs != null) { - for (int i=0; i<repCbs.size(); i++) { - try { - repCbs.get(i).mCallback.opChanged(code, packageName); - } catch (RemoteException e) { - } - } - } - } - - private static HashMap<Callback, ArrayList<Pair<String, Integer>>> addCallbacks( - HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks, - String packageName, int op, ArrayList<Callback> cbs) { - if (cbs == null) { - return callbacks; - } - if (callbacks == null) { - callbacks = new HashMap<Callback, ArrayList<Pair<String, Integer>>>(); - } - for (int i=0; i<cbs.size(); i++) { - Callback cb = cbs.get(i); - ArrayList<Pair<String, Integer>> reports = callbacks.get(cb); - if (reports == null) { - reports = new ArrayList<Pair<String, Integer>>(); - callbacks.put(cb, reports); - } - reports.add(new Pair<String, Integer>(packageName, op)); - } - return callbacks; - } - - @Override - public void resetAllModes() { - mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, - Binder.getCallingPid(), Binder.getCallingUid(), null); - HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null; - synchronized (this) { - boolean changed = false; - for (int i=mUidOps.size()-1; i>=0; i--) { - HashMap<String, Ops> packages = mUidOps.valueAt(i); - Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry<String, Ops> ent = it.next(); - String packageName = ent.getKey(); - Ops pkgOps = ent.getValue(); - for (int j=pkgOps.size()-1; j>=0; j--) { - Op curOp = pkgOps.valueAt(j); - if (AppOpsManager.opAllowsReset(curOp.op) - && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { - curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); - changed = true; - callbacks = addCallbacks(callbacks, packageName, curOp.op, - mOpModeWatchers.get(curOp.op)); - callbacks = addCallbacks(callbacks, packageName, curOp.op, - mPackageModeWatchers.get(packageName)); - if (curOp.time == 0 && curOp.rejectTime == 0) { - pkgOps.removeAt(j); - } - } - } - if (pkgOps.size() == 0) { - it.remove(); - } - } - if (packages.size() == 0) { - mUidOps.removeAt(i); - } - } - if (changed) { - scheduleWriteNowLocked(); - } - } - if (callbacks != null) { - for (Map.Entry<Callback, ArrayList<Pair<String, Integer>>> ent : callbacks.entrySet()) { - Callback cb = ent.getKey(); - ArrayList<Pair<String, Integer>> reports = ent.getValue(); - for (int i=0; i<reports.size(); i++) { - Pair<String, Integer> rep = reports.get(i); - try { - cb.mCallback.opChanged(rep.second, rep.first); - } catch (RemoteException e) { - } - } - } - } - } - - @Override - public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) { - synchronized (this) { - op = AppOpsManager.opToSwitch(op); - Callback cb = mModeWatchers.get(callback.asBinder()); - if (cb == null) { - cb = new Callback(callback); - mModeWatchers.put(callback.asBinder(), cb); - } - if (op != AppOpsManager.OP_NONE) { - ArrayList<Callback> cbs = mOpModeWatchers.get(op); - if (cbs == null) { - cbs = new ArrayList<Callback>(); - mOpModeWatchers.put(op, cbs); - } - cbs.add(cb); - } - if (packageName != null) { - ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName); - if (cbs == null) { - cbs = new ArrayList<Callback>(); - mPackageModeWatchers.put(packageName, cbs); - } - cbs.add(cb); - } - } - } - - @Override - public void stopWatchingMode(IAppOpsCallback callback) { - synchronized (this) { - Callback cb = mModeWatchers.remove(callback.asBinder()); - if (cb != null) { - cb.unlinkToDeath(); - for (int i=mOpModeWatchers.size()-1; i>=0; i--) { - ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i); - cbs.remove(cb); - if (cbs.size() <= 0) { - mOpModeWatchers.removeAt(i); - } - } - for (int i=mPackageModeWatchers.size()-1; i>=0; i--) { - ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i); - cbs.remove(cb); - if (cbs.size() <= 0) { - mPackageModeWatchers.removeAt(i); - } - } - } - } - } - - @Override - public IBinder getToken(IBinder clientToken) { - synchronized (this) { - ClientState cs = mClients.get(clientToken); - if (cs == null) { - cs = new ClientState(clientToken); - mClients.put(clientToken, cs); - } - return cs; - } - } - - @Override - public int checkOperation(int code, int uid, String packageName) { - verifyIncomingUid(uid); - verifyIncomingOp(code); - synchronized (this) { - Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false); - if (op == null) { - return AppOpsManager.opToDefaultMode(code); - } - return op.mode; - } - } - - @Override - public int checkPackage(int uid, String packageName) { - synchronized (this) { - if (getOpsLocked(uid, packageName, true) != null) { - return AppOpsManager.MODE_ALLOWED; - } else { - return AppOpsManager.MODE_ERRORED; - } - } - } - - @Override - public int noteOperation(int code, int uid, String packageName) { - verifyIncomingUid(uid); - verifyIncomingOp(code); - synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); - if (ops == null) { - if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid - + " package " + packageName); - return AppOpsManager.MODE_ERRORED; - } - Op op = getOpLocked(ops, code, true); - if (op.duration == -1) { - Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName - + " code " + code + " time=" + op.time + " duration=" + op.duration); - } - op.duration = 0; - final int switchCode = AppOpsManager.opToSwitch(code); - final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; - if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { - if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code " - + switchCode + " (" + code + ") uid " + uid + " package " + packageName); - op.rejectTime = System.currentTimeMillis(); - return switchOp.mode; - } - if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid - + " package " + packageName); - op.time = System.currentTimeMillis(); - op.rejectTime = 0; - return AppOpsManager.MODE_ALLOWED; - } - } - - @Override - public int startOperation(IBinder token, int code, int uid, String packageName) { - verifyIncomingUid(uid); - verifyIncomingOp(code); - ClientState client = (ClientState)token; - synchronized (this) { - Ops ops = getOpsLocked(uid, packageName, true); - if (ops == null) { - if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid - + " package " + packageName); - return AppOpsManager.MODE_ERRORED; - } - Op op = getOpLocked(ops, code, true); - final int switchCode = AppOpsManager.opToSwitch(code); - final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op; - if (switchOp.mode != AppOpsManager.MODE_ALLOWED) { - if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code " - + switchCode + " (" + code + ") uid " + uid + " package " + packageName); - op.rejectTime = System.currentTimeMillis(); - return switchOp.mode; - } - if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid - + " package " + packageName); - if (op.nesting == 0) { - op.time = System.currentTimeMillis(); - op.rejectTime = 0; - op.duration = -1; - } - op.nesting++; - if (client.mStartedOps != null) { - client.mStartedOps.add(op); - } - return AppOpsManager.MODE_ALLOWED; - } - } - - @Override - public void finishOperation(IBinder token, int code, int uid, String packageName) { - verifyIncomingUid(uid); - verifyIncomingOp(code); - ClientState client = (ClientState)token; - synchronized (this) { - Op op = getOpLocked(code, uid, packageName, true); - if (op == null) { - return; - } - if (client.mStartedOps != null) { - if (!client.mStartedOps.remove(op)) { - throw new IllegalStateException("Operation not started: uid" + op.uid - + " pkg=" + op.packageName + " op=" + op.op); - } - } - finishOperationLocked(op); - } - } - - void finishOperationLocked(Op op) { - if (op.nesting <= 1) { - if (op.nesting == 1) { - op.duration = (int)(System.currentTimeMillis() - op.time); - op.time += op.duration; - } else { - Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg " - + op.packageName + " code " + op.op + " time=" + op.time - + " duration=" + op.duration + " nesting=" + op.nesting); - } - op.nesting = 0; - } else { - op.nesting--; - } - } - - private void verifyIncomingUid(int uid) { - if (uid == Binder.getCallingUid()) { - return; - } - if (Binder.getCallingPid() == Process.myPid()) { - return; - } - mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, - Binder.getCallingPid(), Binder.getCallingUid(), null); - } - - private void verifyIncomingOp(int op) { - if (op >= 0 && op < AppOpsManager._NUM_OP) { - return; - } - throw new IllegalArgumentException("Bad operation #" + op); - } - - private Ops getOpsLocked(int uid, String packageName, boolean edit) { - HashMap<String, Ops> pkgOps = mUidOps.get(uid); - if (pkgOps == null) { - if (!edit) { - return null; - } - pkgOps = new HashMap<String, Ops>(); - mUidOps.put(uid, pkgOps); - } - if (uid == 0) { - packageName = "root"; - } else if (uid == Process.SHELL_UID) { - packageName = "com.android.shell"; - } - Ops ops = pkgOps.get(packageName); - if (ops == null) { - if (!edit) { - return null; - } - // This is the first time we have seen this package name under this uid, - // so let's make sure it is valid. - if (uid != 0) { - final long ident = Binder.clearCallingIdentity(); - try { - int pkgUid = -1; - try { - pkgUid = mContext.getPackageManager().getPackageUid(packageName, - UserHandle.getUserId(uid)); - } catch (NameNotFoundException e) { - if ("media".equals(packageName)) { - pkgUid = Process.MEDIA_UID; - } - } - if (pkgUid != uid) { - // Oops! The package name is not valid for the uid they are calling - // under. Abort. - Slog.w(TAG, "Bad call: specified package " + packageName - + " under uid " + uid + " but it is really " + pkgUid); - return null; - } - } finally { - Binder.restoreCallingIdentity(ident); - } - } - ops = new Ops(packageName, uid); - pkgOps.put(packageName, ops); - } - return ops; - } - - private void scheduleWriteLocked() { - if (!mWriteScheduled) { - mWriteScheduled = true; - mHandler.postDelayed(mWriteRunner, WRITE_DELAY); - } - } - - private void scheduleWriteNowLocked() { - if (!mWriteScheduled) { - mWriteScheduled = true; - } - mHandler.removeCallbacks(mWriteRunner); - mHandler.post(mWriteRunner); - } - - private Op getOpLocked(int code, int uid, String packageName, boolean edit) { - Ops ops = getOpsLocked(uid, packageName, edit); - if (ops == null) { - return null; - } - return getOpLocked(ops, code, edit); - } - - private Op getOpLocked(Ops ops, int code, boolean edit) { - Op op = ops.get(code); - if (op == null) { - if (!edit) { - return null; - } - op = new Op(ops.uid, ops.packageName, code); - ops.put(code, op); - } - if (edit) { - scheduleWriteLocked(); - } - return op; - } - - void readState() { - synchronized (mFile) { - synchronized (this) { - FileInputStream stream; - try { - stream = mFile.openRead(); - } catch (FileNotFoundException e) { - Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); - return; - } - boolean success = false; - try { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(stream, null); - int type; - while ((type = parser.next()) != XmlPullParser.START_TAG - && type != XmlPullParser.END_DOCUMENT) { - ; - } - - if (type != XmlPullParser.START_TAG) { - throw new IllegalStateException("no start tag found"); - } - - int outerDepth = parser.getDepth(); - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("pkg")) { - readPackage(parser); - } else { - Slog.w(TAG, "Unknown element under <app-ops>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - success = true; - } catch (IllegalStateException e) { - Slog.w(TAG, "Failed parsing " + e); - } catch (NullPointerException e) { - Slog.w(TAG, "Failed parsing " + e); - } catch (NumberFormatException e) { - Slog.w(TAG, "Failed parsing " + e); - } catch (XmlPullParserException e) { - Slog.w(TAG, "Failed parsing " + e); - } catch (IOException e) { - Slog.w(TAG, "Failed parsing " + e); - } catch (IndexOutOfBoundsException e) { - Slog.w(TAG, "Failed parsing " + e); - } finally { - if (!success) { - mUidOps.clear(); - } - try { - stream.close(); - } catch (IOException e) { - } - } - } - } - } - - void readPackage(XmlPullParser parser) throws NumberFormatException, - XmlPullParserException, IOException { - String pkgName = parser.getAttributeValue(null, "n"); - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("uid")) { - readUid(parser, pkgName); - } else { - Slog.w(TAG, "Unknown element under <pkg>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - } - - void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, - XmlPullParserException, IOException { - int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - - String tagName = parser.getName(); - if (tagName.equals("op")) { - Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n"))); - String mode = parser.getAttributeValue(null, "m"); - if (mode != null) { - op.mode = Integer.parseInt(mode); - } - String time = parser.getAttributeValue(null, "t"); - if (time != null) { - op.time = Long.parseLong(time); - } - time = parser.getAttributeValue(null, "r"); - if (time != null) { - op.rejectTime = Long.parseLong(time); - } - String dur = parser.getAttributeValue(null, "d"); - if (dur != null) { - op.duration = Integer.parseInt(dur); - } - HashMap<String, Ops> pkgOps = mUidOps.get(uid); - if (pkgOps == null) { - pkgOps = new HashMap<String, Ops>(); - mUidOps.put(uid, pkgOps); - } - Ops ops = pkgOps.get(pkgName); - if (ops == null) { - ops = new Ops(pkgName, uid); - pkgOps.put(pkgName, ops); - } - ops.put(op.op, op); - } else { - Slog.w(TAG, "Unknown element under <pkg>: " - + parser.getName()); - XmlUtils.skipCurrentTag(parser); - } - } - } - - void writeState() { - synchronized (mFile) { - List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); - - FileOutputStream stream; - try { - stream = mFile.startWrite(); - } catch (IOException e) { - Slog.w(TAG, "Failed to write state: " + e); - return; - } - - try { - XmlSerializer out = new FastXmlSerializer(); - out.setOutput(stream, "utf-8"); - out.startDocument(null, true); - out.startTag(null, "app-ops"); - - if (allOps != null) { - String lastPkg = null; - for (int i=0; i<allOps.size(); i++) { - AppOpsManager.PackageOps pkg = allOps.get(i); - if (!pkg.getPackageName().equals(lastPkg)) { - if (lastPkg != null) { - out.endTag(null, "pkg"); - } - lastPkg = pkg.getPackageName(); - out.startTag(null, "pkg"); - out.attribute(null, "n", lastPkg); - } - out.startTag(null, "uid"); - out.attribute(null, "n", Integer.toString(pkg.getUid())); - List<AppOpsManager.OpEntry> ops = pkg.getOps(); - for (int j=0; j<ops.size(); j++) { - AppOpsManager.OpEntry op = ops.get(j); - out.startTag(null, "op"); - out.attribute(null, "n", Integer.toString(op.getOp())); - if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) { - out.attribute(null, "m", Integer.toString(op.getMode())); - } - long time = op.getTime(); - if (time != 0) { - out.attribute(null, "t", Long.toString(time)); - } - time = op.getRejectTime(); - if (time != 0) { - out.attribute(null, "r", Long.toString(time)); - } - int dur = op.getDuration(); - if (dur != 0) { - out.attribute(null, "d", Integer.toString(dur)); - } - out.endTag(null, "op"); - } - out.endTag(null, "uid"); - } - if (lastPkg != null) { - out.endTag(null, "pkg"); - } - } - - out.endTag(null, "app-ops"); - out.endDocument(); - mFile.finishWrite(stream); - } catch (IOException e) { - Slog.w(TAG, "Failed to write state, restoring backup.", e); - mFile.failWrite(stream); - } - } - } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump ApOps service from from pid=" - + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid()); - return; - } - - synchronized (this) { - pw.println("Current AppOps Service state:"); - final long now = System.currentTimeMillis(); - boolean needSep = false; - if (mOpModeWatchers.size() > 0) { - needSep = true; - pw.println(" Op mode watchers:"); - for (int i=0; i<mOpModeWatchers.size(); i++) { - pw.print(" Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i))); - pw.println(":"); - ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i); - for (int j=0; j<callbacks.size(); j++) { - pw.print(" #"); pw.print(j); pw.print(": "); - pw.println(callbacks.get(j)); - } - } - } - if (mPackageModeWatchers.size() > 0) { - needSep = true; - pw.println(" Package mode watchers:"); - for (int i=0; i<mPackageModeWatchers.size(); i++) { - pw.print(" Pkg "); pw.print(mPackageModeWatchers.keyAt(i)); - pw.println(":"); - ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i); - for (int j=0; j<callbacks.size(); j++) { - pw.print(" #"); pw.print(j); pw.print(": "); - pw.println(callbacks.get(j)); - } - } - } - if (mModeWatchers.size() > 0) { - needSep = true; - pw.println(" All mode watchers:"); - for (int i=0; i<mModeWatchers.size(); i++) { - pw.print(" "); pw.print(mModeWatchers.keyAt(i)); - pw.print(" -> "); pw.println(mModeWatchers.valueAt(i)); - } - } - if (mClients.size() > 0) { - needSep = true; - pw.println(" Clients:"); - for (int i=0; i<mClients.size(); i++) { - pw.print(" "); pw.print(mClients.keyAt(i)); pw.println(":"); - ClientState cs = mClients.valueAt(i); - pw.print(" "); pw.println(cs); - if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) { - pw.println(" Started ops:"); - for (int j=0; j<cs.mStartedOps.size(); j++) { - Op op = cs.mStartedOps.get(j); - 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)); - } - } - } - } - if (needSep) { - pw.println(); - } - for (int i=0; i<mUidOps.size(); i++) { - pw.print(" Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":"); - HashMap<String, Ops> pkgOps = mUidOps.valueAt(i); - for (Ops ops : pkgOps.values()) { - pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); - for (int j=0; j<ops.size(); j++) { - Op op = ops.valueAt(j); - pw.print(" "); pw.print(AppOpsManager.opToName(op.op)); - pw.print(": mode="); pw.print(op.mode); - if (op.time != 0) { - pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw); - pw.print(" ago"); - } - if (op.rejectTime != 0) { - pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw); - pw.print(" ago"); - } - if (op.duration == -1) { - pw.println(" (running)"); - } else { - pw.print("; duration="); - TimeUtils.formatDuration(op.duration, pw); - pw.println(); - } - } - } - } - } - } -} |