AppOpsService.java revision 72e3983d38f656cfa8c7a038eb80bdd9ea06768e
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 13072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) { 13172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = null; 13272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (ops == null) { 13372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 13472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn for (int j=0; j<pkgOps.size(); j++) { 13572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Op curOp = pkgOps.valueAt(j); 13672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time, 13772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn curOp.duration)); 13872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 13972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } else { 14072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn for (int j=0; j<ops.length; j++) { 14172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Op curOp = pkgOps.get(ops[j]); 14272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (curOp != null) { 14372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (resOps == null) { 14472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps = new ArrayList<AppOpsManager.OpEntry>(); 14572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 14672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time, 14772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn curOp.duration)); 14872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 14972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 15072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 15172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return resOps; 15272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 15372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 154a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 15535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) { 15635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 15735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 15835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ArrayList<AppOpsManager.PackageOps> res = null; 159a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 16035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int i=0; i<mUidOps.size(); i++) { 16135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn HashMap<String, Ops> packages = mUidOps.valueAt(i); 16235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (Ops pkgOps : packages.values()) { 16372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 16435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (resOps != null) { 16535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (res == null) { 16635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res = new ArrayList<AppOpsManager.PackageOps>(); 16735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 16835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 16935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps.packageName, pkgOps.uid, resOps); 17035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn res.add(resPackage); 17135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 17235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 173a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 174a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 17535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return res; 176a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 177a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 178a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 17972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, 18072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn int[] ops) { 18172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS, 18272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 18372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn synchronized (this) { 18472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Ops pkgOps = getOpsLocked(uid, packageName, false); 18572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (pkgOps == null) { 18672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 18772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 18872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops); 18972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (resOps == null) { 19072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 19172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 19272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>(); 19372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps( 19472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn pkgOps.packageName, pkgOps.uid, resOps); 19572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn res.add(resPackage); 19672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return res; 19772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 19872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 19972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 20072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn @Override 20135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int checkOperation(int code, int uid, String packageName) { 202a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 203a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 20435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, false); 205a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 20635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_ALLOWED; 207a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 211a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 212a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 21335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int noteOperation(int code, int uid, String packageName) { 214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 215a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 21635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 217a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 21835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_IGNORED; 219a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 22035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.duration == -1) { 22135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName 222a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + " code " + code + " time=" + op.time + " duration=" + op.duration); 223a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 22435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = System.currentTimeMillis(); 22535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = 0; 226a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 22735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return AppOpsManager.MODE_ALLOWED; 228a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 229a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 230a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 23135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public int startOperation(int code, int uid, String packageName) { 232a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 233a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 23435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 235a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 236a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_IGNORED; 237a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 23835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting == 0) { 23935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = System.currentTimeMillis(); 24035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = -1; 241a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 24235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.nesting++; 243a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 244a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return AppOpsManager.MODE_ALLOWED; 245a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 246a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 24835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn public void finishOperation(int code, int uid, String packageName) { 249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn uid = handleIncomingUid(uid); 250a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 25135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = getOpLocked(code, uid, packageName, true); 252a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 253a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 254a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 25535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting <= 1) { 25635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (op.nesting == 1) { 25735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = (int)(System.currentTimeMillis() - op.time); 25835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 25935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg " + packageName 26035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + " code " + code + " time=" + op.time + " duration=" + op.duration 26135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + " nesting=" + op.nesting); 26235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 263e799175b6ba3aadd972f4b861758d675d1f93987Dianne Hackborn op.nesting = 0; 26435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 26535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.nesting--; 266a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 267a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 268a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 269a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 270a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int handleIncomingUid(int uid) { 271a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (uid == Binder.getCallingUid()) { 272a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 273a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 274a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 275a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 276a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 277a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 278a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 279a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return uid; 280a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 281a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 28272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn private Ops getOpsLocked(int uid, String packageName, boolean edit) { 283a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.get(uid); 284a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (pkgOps == null) { 28535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 28635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 28735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 288a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pkgOps = new HashMap<String, Ops>(); 289a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mUidOps.put(uid, pkgOps); 290a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 291a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Ops ops = pkgOps.get(packageName); 292a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (ops == null) { 29335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 29535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 296a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // This is the first time we have seen this package name under this uid, 297a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn // so let's make sure it is valid. 298002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 299002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn try { 300002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn int pkgUid = -1; 301a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 302002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn pkgUid = mContext.getPackageManager().getPackageUid(packageName, 303002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn UserHandle.getUserId(uid)); 304002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } catch (NameNotFoundException e) { 305a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 306002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn if (pkgUid != uid) { 307002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn // Oops! The package name is not valid for the uid they are calling 308002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn // under. Abort. 309002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn Slog.w(TAG, "Bad call: specified package " + packageName 310002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn + " under uid " + uid + " but it is really " + pkgUid); 311002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn return null; 312002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } 313002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn } finally { 314002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn Binder.restoreCallingIdentity(ident); 315a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 31635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops = new Ops(packageName, uid); 317a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pkgOps.put(packageName, ops); 318a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 31972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return ops; 32072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 32172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn 32272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn private Op getOpLocked(int code, int uid, String packageName, boolean edit) { 32372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn Ops ops = getOpsLocked(uid, packageName, edit); 32472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn if (ops == null) { 32572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn return null; 32672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn } 327a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.get(code); 328a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op == null) { 32935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!edit) { 33035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return null; 33135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 332a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn op = new Op(code); 333a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn ops.put(code, op); 334a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 33535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (edit && !mWriteScheduled) { 33635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mWriteScheduled = true; 33735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mHandler.postDelayed(mWriteRunner, WRITE_DELAY); 33835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 339a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return op; 340a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 341a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 34235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readState() { 34335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 34435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (this) { 34535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileInputStream stream; 34635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 34735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.openRead(); 34835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (FileNotFoundException e) { 34935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty"); 35035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 35135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 35235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn boolean success = false; 35335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 35435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParser parser = Xml.newPullParser(); 35535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn parser.setInput(stream, null); 35635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 35735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.START_TAG 35835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && type != XmlPullParser.END_DOCUMENT) { 35935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ; 36035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 36235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type != XmlPullParser.START_TAG) { 36335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn throw new IllegalStateException("no start tag found"); 36435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 36535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 36635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 36735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 36835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 36935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 37035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 37135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 37235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 37335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 37435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("pkg")) { 37535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readPackage(parser); 37635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 37735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <app-ops>: " 37835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 37935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 38035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 38135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 38235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn success = true; 38335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IllegalStateException e) { 38435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 38535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NullPointerException e) { 38635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 38735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (NumberFormatException e) { 38835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 38935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (XmlPullParserException e) { 39035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 39135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 39235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 39335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IndexOutOfBoundsException e) { 39435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed parsing " + e); 39535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } finally { 39635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!success) { 39735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mUidOps.clear(); 39835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 39935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 40035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream.close(); 40135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 40235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 40735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 40835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void readPackage(XmlPullParser parser) throws NumberFormatException, 40935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 41035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String pkgName = parser.getAttributeValue(null, "n"); 41135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 41235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 41335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 41435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 41535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 41635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 41735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 41835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 41935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 42035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("uid")) { 42135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn readUid(parser, pkgName); 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 readUid(XmlPullParser parser, String pkgName) throws NumberFormatException, 43135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlPullParserException, IOException { 43235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int uid = Integer.parseInt(parser.getAttributeValue(null, "n")); 43335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int outerDepth = parser.getDepth(); 43435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn int type; 43535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 43635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 43735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 43835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn continue; 43935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 44035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 44135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String tagName = parser.getName(); 44235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (tagName.equals("op")) { 44335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n"))); 44435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.time = Long.parseLong(parser.getAttributeValue(null, "t")); 44535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn op.duration = Integer.parseInt(parser.getAttributeValue(null, "d")); 44635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.get(uid); 44735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (pkgOps == null) { 44835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps = new HashMap<String, Ops>(); 44935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mUidOps.put(uid, pkgOps); 45035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 45135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Ops ops = pkgOps.get(pkgName); 45235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (ops == null) { 45335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops = new Ops(pkgName, uid); 45435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn pkgOps.put(pkgName, ops); 45535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 45635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn ops.put(op.op, op); 45735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } else { 45835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Unknown element under <pkg>: " 45935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn + parser.getName()); 46035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlUtils.skipCurrentTag(parser); 46135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 46235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 46335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 46435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 46535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn void writeState() { 46635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn synchronized (mFile) { 46735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null); 46835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 46935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn FileOutputStream stream; 47035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 47135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn stream = mFile.startWrite(); 47235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 47335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state: " + e); 47435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn return; 47535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 47635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 47735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn try { 47835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn XmlSerializer out = new FastXmlSerializer(); 47935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.setOutput(stream, "utf-8"); 48035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startDocument(null, true); 48135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "app-ops"); 48235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 48335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (allOps != null) { 48435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn String lastPkg = null; 48535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int i=0; i<allOps.size(); i++) { 48635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.PackageOps pkg = allOps.get(i); 48735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (!pkg.getPackageName().equals(lastPkg)) { 48835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 48935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 49035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 49135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn lastPkg = pkg.getPackageName(); 49235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "pkg"); 49335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", lastPkg); 49435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 49535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "uid"); 49635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(pkg.getUid())); 49735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn List<AppOpsManager.OpEntry> ops = pkg.getOps(); 49835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn for (int j=0; j<ops.size(); j++) { 49935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn AppOpsManager.OpEntry op = ops.get(j); 50035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.startTag(null, "op"); 50135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "n", Integer.toString(op.getOp())); 50235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "t", Long.toString(op.getTime())); 50335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.attribute(null, "d", Integer.toString(op.getDuration())); 50435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "op"); 50535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 50635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "uid"); 50735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 50835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn if (lastPkg != null) { 50935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "pkg"); 51035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 51135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 51235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 51335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endTag(null, "app-ops"); 51435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn out.endDocument(); 51535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.finishWrite(stream); 51635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } catch (IOException e) { 51735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Slog.w(TAG, "Failed to write state, restoring backup.", e); 51835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mFile.failWrite(stream); 51935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 52035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 52135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn } 52235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn 523a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn @Override 524a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 525a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 526a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn != PackageManager.PERMISSION_GRANTED) { 527a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Permission Denial: can't dump ApOps service from from pid=" 528a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + Binder.getCallingPid() 529a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn + ", uid=" + Binder.getCallingUid()); 530a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 531a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 532a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 533a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (this) { 534a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println("Current AppOps Service state:"); 535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (int i=0; i<mUidOps.size(); i++) { 536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":"); 537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn HashMap<String, Ops> pkgOps = mUidOps.valueAt(i); 538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (Ops ops : pkgOps.values()) { 539a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" Package "); pw.print(ops.packageName); pw.println(":"); 540a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn for (int j=0; j<ops.size(); j++) { 541a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Op op = ops.valueAt(j); 542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" "); pw.print(AppOpsManager.opToString(op.op)); 543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(": time="); 544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw); 545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print(" ago"); 546a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (op.duration == -1) { 547a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println(" (running)"); 548a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } else { 549a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.print("; duration="); 550a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn TimeUtils.formatDuration(op.duration, pw); 551a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn pw.println(); 552a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 553a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 554a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 555a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 556a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 557a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 558a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn} 559