AppOpsService.java revision e799175b6ba3aadd972f4b861758d675d1f93987
1a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn/* 2a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Copyright (C) 2012 The Android Open Source Project 3a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 4a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); 5a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * you may not use this file except in compliance with the License. 6a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * You may obtain a copy of the License at 7a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 8a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 9a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * 10a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 11a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, 12a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * See the License for the specific language governing permissions and 14a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * limitations under the License. 15a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn */ 16a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 17a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpackage com.android.server; 18a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.File; 20a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.FileDescriptor; 2135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileInputStream; 2235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileNotFoundException; 2335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileOutputStream; 2435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.IOException; 25a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.PrintWriter; 2635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.ArrayList; 27a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.util.HashMap; 2835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.List; 29a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 30a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager; 31a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.Context; 32a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager; 33a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException; 3435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.AsyncTask; 35a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Binder; 3635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.Handler; 37a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Process; 38a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 39a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.UserHandle; 40a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile; 41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog; 42a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray; 43a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils; 4435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml; 45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 4735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer; 4835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils; 4935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 5035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser; 5135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException; 5235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer; 53a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 54a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub { 55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn static final String TAG = "AppOps"; 5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn static final boolean DEBUG = false; 5735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 5835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn // Write at most every 30 minutes. 5935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000; 60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 61a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Context mContext; 62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final AtomicFile mFile; 6335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn final Handler mHandler; 6435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 6535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean mWriteScheduled; 6635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn final Runnable mWriteRunner = new Runnable() { 6735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public void run() { 6835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (AppOpsService.this) { 6935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = false; 7035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() { 7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn @Override protected Void doInBackground(Void... params) { 7235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn writeState(); 7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 7535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn }; 7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null); 7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 7935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn }; 80a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 81a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final SparseArray<HashMap<String, Ops>> mUidOps 82a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn = new SparseArray<HashMap<String, Ops>>(); 83a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final static class Ops extends SparseArray<Op> { 85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public final String packageName; 8635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public final int uid; 87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 8835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public Ops(String _packageName, int _uid) { 89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn packageName = _packageName; 9035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn uid = _uid; 91a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 92a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 94a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final static class Op { 95a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public final int op; 96a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public int duration; 97a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public long time; 9835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int nesting; 99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 100a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public Op(int _op) { 101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn op = _op; 102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 103a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 104a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 10535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public AppOpsService(File storagePath) { 10635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile = new AtomicFile(storagePath); 10735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mHandler = new Handler(); 10835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readState(); 109a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 110a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 111a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void publish(Context context) { 112a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mContext = context; 113a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder()); 114a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 115a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 116a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn public void shutdown() { 117a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Writing app ops before shutdown..."); 11835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean doWrite = false; 11935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (this) { 12035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (mWriteScheduled) { 12135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = false; 12235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn doWrite = true; 12335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 12435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 12535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (doWrite) { 12635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn writeState(); 12735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 128a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 129a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 130a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 13135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 13235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 13335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 13435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ArrayList<AppOpsManager.PackageOps> res = null; 135a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 13635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int i=0; i<mUidOps.size(); i++) { 13735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn HashMap<String, Ops> packages = mUidOps.valueAt(i); 13835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (Ops pkgOps : packages.values()) { 13935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = null; 14035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (ops == null) { 14135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 14235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int j=0; j<pkgOps.size(); j++) { 14335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op curOp = pkgOps.valueAt(j); 14435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time, 14535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn curOp.duration)); 14635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 14735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 14835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int j=0; j<ops.length; j++) { 14935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op curOp = pkgOps.get(ops[j]); 15035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (curOp != null) { 15135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (resOps == null) { 15235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 15335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 15435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time, 15535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn curOp.duration)); 15635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 15735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 15835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 15935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (resOps != null) { 16035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (res == null) { 16135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res = new ArrayList<AppOpsManager.PackageOps>(); 16235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 16335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 16435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps.packageName, pkgOps.uid, resOps); 16535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res.add(resPackage); 16635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 16735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 168a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 169a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 17035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return res; 171a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 172a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 173a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 17435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int checkOperation(int code, int uid, String packageName) { 175a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 176a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 17735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, false); 178a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 17935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_ALLOWED; 180a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 181a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 182a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 183a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 184a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 185a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 18635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int noteOperation(int code, int uid, String packageName) { 187a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 188a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 18935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 190a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 19135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_IGNORED; 192a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 19335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.duration == -1) { 19435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 195a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + " code " + code + " time=" + op.time + " duration=" + op.duration); 196a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 19735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = System.currentTimeMillis(); 19835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = 0; 199a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 20035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_ALLOWED; 201a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 202a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 203a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 20435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int startOperation(int code, int uid, String packageName) { 205a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 206a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 20735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_IGNORED; 210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 21135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting == 0) { 21235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = System.currentTimeMillis(); 21335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = -1; 214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 21535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.nesting++; 216a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 217a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 218a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 219a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 220a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 22135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public void finishOperation(int code, int uid, String packageName) { 222a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 223a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 22435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 225a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 226a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 227a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 22835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting <= 1) { 22935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting == 1) { 23035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = (int)(System.currentTimeMillis() - op.time); 23135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 23235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg " + packageName 23335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + " code " + code + " time=" + op.time + " duration=" + op.duration 23435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + " nesting=" + op.nesting); 23535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 236e799175b6ba3aadd972f4b861758d675d1f93987Dianne Hackborn op.nesting = 0; 23735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 23835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.nesting--; 239a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 240a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 241a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 242a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 243a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int handleIncomingUid(int uid) { 244a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (uid == Binder.getCallingUid()) { 245a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 246a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 248a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 250a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 251a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 252a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 253a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 254a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 25535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 256a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.get(uid); 257a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (pkgOps == null) { 25835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 25935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 26035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 261a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pkgOps = new HashMap<String, Ops>(); 262a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mUidOps.put(uid, pkgOps); 263a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 264a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Ops ops = pkgOps.get(packageName); 265a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (ops == null) { 26635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 26735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 26835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 269a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // This is the first time we have seen this package name under this uid, 270a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // so let's make sure it is valid. 271002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 272002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn try { 273002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn int pkgUid = -1; 274a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 275002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn pkgUid = mContext.getPackageManager().getPackageUid(packageName, 276002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn UserHandle.getUserId(uid)); 277002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } catch (NameNotFoundException e) { 278a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 279002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn if (pkgUid != uid) { 280002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn // Oops! The package name is not valid for the uid they are calling 281002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn // under. Abort. 282002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn Slog.w(TAG, "Bad call: specified package " + packageName 283002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn + " under uid " + uid + " but it is really " + pkgUid); 284002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn return null; 285002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } 286002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } finally { 287002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn Binder.restoreCallingIdentity(ident); 288a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 28935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops = new Ops(packageName, uid); 290a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pkgOps.put(packageName, ops); 291a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 292a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.get(code); 293a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 29535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 29635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 297a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn op = new Op(code); 298a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn ops.put(code, op); 299a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 30035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (edit && !mWriteScheduled) { 30135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = true; 30235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 30335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 304a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return op; 305a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 306a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 30735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readState() { 30835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 30935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (this) { 31035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileInputStream stream; 31135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 31235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.openRead(); 31335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (FileNotFoundException e) { 31435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 31535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 31635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 31735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean success = false; 31835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 31935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParser parser = Xml.newPullParser(); 32035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn parser.setInput(stream, null); 32135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 32235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.START_TAG 32335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && type != XmlPullParser.END_DOCUMENT) { 32435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ; 32535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 32635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 32735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type != XmlPullParser.START_TAG) { 32835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn throw new IllegalStateException("no start tag found"); 32935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 33035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 33135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 33235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 33335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 33435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 33535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 33635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 33735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 33835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 33935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("pkg")) { 34035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readPackage(parser); 34135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 34235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <app-ops>: " 34335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 34435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 34535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 34635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 34735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn success = true; 34835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IllegalStateException e) { 34935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 35035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NullPointerException e) { 35135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 35235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NumberFormatException e) { 35335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 35435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (XmlPullParserException e) { 35535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 35635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 35735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 35835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IndexOutOfBoundsException e) { 35935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 36035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } finally { 36135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!success) { 36235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mUidOps.clear(); 36335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 36535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream.close(); 36635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 36735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 37035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 37135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 37235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 37335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readPackage(XmlPullParser parser) throws NumberFormatException, 37435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 37535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String pkgName = parser.getAttributeValue(null, "n"); 37635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 37735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 37835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 37935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 38035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 38135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 38235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 38335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 38435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 38535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("uid")) { 38635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readUid(parser, pkgName); 38735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 38835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <pkg>: " 38935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 39035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 39135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 39235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 39335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 39435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 39535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 39635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 39735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 39835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 39935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 40035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 40135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 40235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 40335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 40435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 40635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 40735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("op")) { 40835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n"))); 40935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = Long.parseLong(parser.getAttributeValue(null, "t")); 41035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = Integer.parseInt(parser.getAttributeValue(null, "d")); 41135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.get(uid); 41235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (pkgOps == null) { 41335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps = new HashMap<String, Ops>(); 41435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mUidOps.put(uid, pkgOps); 41535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 41635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Ops ops = pkgOps.get(pkgName); 41735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (ops == null) { 41835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops = new Ops(pkgName, uid); 41935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps.put(pkgName, ops); 42035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops.put(op.op, op); 42235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 42335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <pkg>: " 42435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 42535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 42635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 42935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 43035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void writeState() { 43135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 43235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 43335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 43435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileOutputStream stream; 43535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 43635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.startWrite(); 43735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 43835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state: " + e); 43935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 44035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 44135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 44235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 44335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlSerializer out = new FastXmlSerializer(); 44435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.setOutput(stream, "utf-8"); 44535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startDocument(null, true); 44635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "app-ops"); 44735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 44835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (allOps != null) { 44935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String lastPkg = null; 45035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int i=0; i<allOps.size(); i++) { 45135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps pkg = allOps.get(i); 45235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!pkg.getPackageName().equals(lastPkg)) { 45335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 45435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 45535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 45635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn lastPkg = pkg.getPackageName(); 45735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "pkg"); 45835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", lastPkg); 45935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 46035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "uid"); 46135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(pkg.getUid())); 46235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.OpEntry> ops = pkg.getOps(); 46335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int j=0; j<ops.size(); j++) { 46435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.OpEntry op = ops.get(j); 46535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "op"); 46635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(op.getOp())); 46735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "t", Long.toString(op.getTime())); 46835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "d", Integer.toString(op.getDuration())); 46935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "op"); 47035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 47135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "uid"); 47235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 47335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 47435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 47535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 47635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 47735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 47835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "app-ops"); 47935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endDocument(); 48035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.finishWrite(stream); 48135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 48235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state, restoring backup.", e); 48335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.failWrite(stream); 48435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 48535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 48635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 48735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 488a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 489a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 490a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 491a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn != PackageManager.PERMISSION_GRANTED) { 492a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Permission Denial: can't dump ApOps service from from pid=" 493a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + Binder.getCallingPid() 494a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + ", uid=" + Binder.getCallingUid()); 495a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 496a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 497a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 498a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 499a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Current AppOps Service state:"); 500a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (int i=0; i<mUidOps.size(); i++) { 501a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":"); 502a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.valueAt(i); 503a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (Ops ops : pkgOps.values()) { 504a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 505a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (int j=0; j<ops.size(); j++) { 506a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.valueAt(j); 507a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" "); pw.print(AppOpsManager.opToString(op.op)); 508a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(": time="); 509a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw); 510a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" ago"); 511a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op.duration == -1) { 512a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println(" (running)"); 513a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } else { 514a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print("; duration="); 515a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn TimeUtils.formatDuration(op.duration, pw); 516a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println(); 517a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 518a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 519a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 520a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 521a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 522a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 523a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn} 524