AppOpsService.java revision c2293025a25e04b26bf53713d71f85fd9ca5e8e9
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;
28c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport java.util.Iterator;
2935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.List;
30a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
31a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
32a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.Context;
33a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager;
34a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
3535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.AsyncTask;
36a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Binder;
3735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.Handler;
38c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.IBinder;
39a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Process;
40c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.RemoteException;
41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager;
42a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.UserHandle;
43a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile;
445e45ee6752528791deb66b83d76250685de15d47Dianne Hackbornimport android.util.Log;
45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog;
46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray;
47a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils;
4835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml;
49a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
50a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
51c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport com.android.internal.app.IAppOpsCallback;
5235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
5335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils;
5435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
5535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser;
5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
5735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer;
58a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub {
60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    static final String TAG = "AppOps";
6135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final boolean DEBUG = false;
6235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
6335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    // Write at most every 30 minutes.
6435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
65a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
66a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    Context mContext;
67a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final AtomicFile mFile;
6835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Handler mHandler;
6935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
7035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    boolean mWriteScheduled;
7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Runnable mWriteRunner = new Runnable() {
7235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public void run() {
7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (AppOpsService.this) {
7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
7535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    @Override protected Void doInBackground(Void... params) {
7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        writeState();
7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        return null;
7935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
8035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                };
8135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
8235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
8335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
8435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    };
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final SparseArray<HashMap<String, Ops>> mUidOps
87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            = new SparseArray<HashMap<String, Ops>>();
88a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
89c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Ops extends SparseArray<Op> {
90a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final String packageName;
9135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public final int uid;
92a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
9335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public Ops(String _packageName, int _uid) {
94a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            packageName = _packageName;
9535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            uid = _uid;
96a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
97a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
99c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Op {
100a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final int op;
1015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public int mode;
102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public int duration;
103a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public long time;
1045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public long rejectTime;
10535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public int nesting;
106a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
107a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public Op(int _op) {
108a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = _op;
1095e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mode = AppOpsManager.MODE_ALLOWED;
110a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
111a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
112a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
113c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    final SparseArray<ArrayList<Callback>> mOpModeWatchers
114c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            = new SparseArray<ArrayList<Callback>>();
115c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    final HashMap<String, ArrayList<Callback>> mPackageModeWatchers
116c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            = new HashMap<String, ArrayList<Callback>>();
117c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    final HashMap<IBinder, Callback> mModeWatchers
118c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            = new HashMap<IBinder, Callback>();
119c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
120c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final class Callback implements DeathRecipient {
121c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        final IAppOpsCallback mCallback;
122c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
123c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public Callback(IAppOpsCallback callback) {
124c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback = callback;
125c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            try {
126c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mCallback.asBinder().linkToDeath(this, 0);
127c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            } catch (RemoteException e) {
128c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
129c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
130c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
131c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void unlinkToDeath() {
132c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback.asBinder().unlinkToDeath(this, 0);
133c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
134c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
135c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        @Override
136c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void binderDied() {
137c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            stopWatchingMode(mCallback);
138c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
139c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
140c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
14135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public AppOpsService(File storagePath) {
14235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mFile = new AtomicFile(storagePath);
14335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mHandler = new Handler();
14435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        readState();
145a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
146a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
147a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void publish(Context context) {
148a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext = context;
149a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
150a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
151a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
152a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void shutdown() {
153a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Slog.w(TAG, "Writing app ops before shutdown...");
15435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        boolean doWrite = false;
15535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (this) {
15635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mWriteScheduled) {
15735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
15835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                doWrite = true;
15935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
16035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
16135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (doWrite) {
16235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            writeState();
16335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
164a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
165a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
16672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
16772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        ArrayList<AppOpsManager.OpEntry> resOps = null;
16872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
16972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            resOps = new ArrayList<AppOpsManager.OpEntry>();
17072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<pkgOps.size(); j++) {
17172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.valueAt(j);
1725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
1735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        curOp.rejectTime, curOp.duration));
17472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
17572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        } else {
17672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<ops.length; j++) {
17772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.get(ops[j]);
17872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                if (curOp != null) {
17972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    if (resOps == null) {
18072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                        resOps = new ArrayList<AppOpsManager.OpEntry>();
18172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    }
1825e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
1835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            curOp.rejectTime, curOp.duration));
18472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                }
18572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
18672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
18772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return resOps;
18872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
18972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
190a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
19135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
19235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
19335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
19435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        ArrayList<AppOpsManager.PackageOps> res = null;
195a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
19635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
19735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> packages = mUidOps.valueAt(i);
19835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                for (Ops pkgOps : packages.values()) {
19972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
20035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (resOps != null) {
20135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (res == null) {
20235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            res = new ArrayList<AppOpsManager.PackageOps>();
20335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
20435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
20535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                pkgOps.packageName, pkgOps.uid, resOps);
20635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        res.add(resPackage);
20735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
20835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
21135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return res;
212a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
213a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
21572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
21672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            int[] ops) {
21772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
21872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
21972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        synchronized (this) {
22072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            Ops pkgOps = getOpsLocked(uid, packageName, false);
22172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (pkgOps == null) {
22272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
22372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
22472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
22572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (resOps == null) {
22672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
22772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
22872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
22972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
23072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    pkgOps.packageName, pkgOps.uid, resOps);
23172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            res.add(resPackage);
23272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return res;
23372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
23472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
23572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
23672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    @Override
2375e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public void setMode(int code, int uid, String packageName, int mode) {
238f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
239961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
240c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        ArrayList<Callback> repCbs = null;
241c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        code = AppOpsManager.opToSwitch(code);
2425e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        synchronized (this) {
243c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
2445e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (op != null) {
2455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (op.mode != mode) {
2465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.mode = mode;
247c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.get(code);
248c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
249c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
250c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
251c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
252c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
253c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
254c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = mPackageModeWatchers.get(packageName);
255c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
256c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
257c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
258c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
259c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
260c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
2615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    scheduleWriteNowLocked();
2625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
2635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
2645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
265c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        if (repCbs != null) {
266c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            for (int i=0; i<repCbs.size(); i++) {
267c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                try {
268c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    repCbs.get(i).mCallback.opChanged(code, packageName);
269c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                } catch (RemoteException e) {
270c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
271c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
272c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
273c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
274c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
275c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
276c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
277c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
278c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            op = AppOpsManager.opToSwitch(op);
279c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.get(callback.asBinder());
280c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb == null) {
281c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb = new Callback(callback);
282c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mModeWatchers.put(callback.asBinder(), cb);
283c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
284c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (op != AppOpsManager.OP_NONE) {
285c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mOpModeWatchers.get(op);
286c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
287c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
288c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mOpModeWatchers.put(op, cbs);
289c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
290c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
291c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
292c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (packageName != null) {
293c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
294c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
295c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
296c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mPackageModeWatchers.put(packageName, cbs);
297c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
298c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
299c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
300c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
301c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
302c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
303c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
304c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void stopWatchingMode(IAppOpsCallback callback) {
305c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
306c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.remove(callback.asBinder());
307c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb != null) {
308c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb.unlinkToDeath();
309c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                for (int i=0; i<mOpModeWatchers.size(); i++) {
310c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
311c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs.remove(cb);
312c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs.size() <= 0) {
313c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        mOpModeWatchers.removeAt(i);
314c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
315c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
316c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (mPackageModeWatchers.size() > 0) {
317c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    Iterator<ArrayList<Callback>> it = mPackageModeWatchers.values().iterator();
318c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    while (it.hasNext()) {
319c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        ArrayList<Callback> cbs = it.next();
320c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        cbs.remove(cb);
321c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (cbs.size() <= 0) {
322c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            it.remove();
323c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
324c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
325c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
326c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
327c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
3285e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
3295e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
3305e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    @Override
33135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int checkOperation(int code, int uid, String packageName) {
332f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
333961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
334a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
335f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
336a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
33735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_ALLOWED;
338a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
3395e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return op.mode;
340a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
341a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
342a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
343a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
34435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int noteOperation(int code, int uid, String packageName) {
345f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
346961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
347a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
348f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
349f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
3505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
3515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
35235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_IGNORED;
353a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
354f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
35535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.duration == -1) {
35635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
357a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
358a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
35935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.duration = 0;
360f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
361f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
362f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
363f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
364f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
3655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
366f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
3675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
3685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
3695e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
3705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            op.time = System.currentTimeMillis();
3715e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
372a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
373a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
374a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
375a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
37635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int startOperation(int code, int uid, String packageName) {
377f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
378961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
379a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
380f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
381f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
3825e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
3835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
384a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return AppOpsManager.MODE_IGNORED;
385a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
386f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
387f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
388f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
389f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
390f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
391f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
3925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
393f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
3945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
3955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
3965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
39735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting == 0) {
39835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = System.currentTimeMillis();
39935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = -1;
400a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
40135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.nesting++;
4025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
403a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
404a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
405a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
406a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
40735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public void finishOperation(int code, int uid, String packageName) {
408f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
409961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
410a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
41135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
412a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
413a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
414a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
41535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting <= 1) {
41635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (op.nesting == 1) {
41735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    op.duration = (int)(System.currentTimeMillis() - op.time);
41835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } else {
41935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg " + packageName
42035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration
42135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + " nesting=" + op.nesting);
42235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
423e799175b6ba3aadd972f4b861758d675d1f93987Dianne Hackborn                op.nesting = 0;
42435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
42535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.nesting--;
426a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
427a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
428a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
429a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
430f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
431a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (uid == Binder.getCallingUid()) {
432f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
433a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
434a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
435f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
436a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
437a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
438a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
439a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
440a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
441961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    private void verifyIncomingOp(int op) {
442961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        if (op >= 0 && op < AppOpsManager._NUM_OP) {
443961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn            return;
444961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        }
445961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        throw new IllegalArgumentException("Bad operation #" + op);
446961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    }
447961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn
44872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
449a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        HashMap<String, Ops> pkgOps = mUidOps.get(uid);
450a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (pkgOps == null) {
45135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
45235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
45335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
454a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps = new HashMap<String, Ops>();
455a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mUidOps.put(uid, pkgOps);
456a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
457a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Ops ops = pkgOps.get(packageName);
458a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (ops == null) {
45935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
46035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
46135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
462a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // This is the first time we have seen this package name under this uid,
463a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // so let's make sure it is valid.
464002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            final long ident = Binder.clearCallingIdentity();
465002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            try {
466002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                int pkgUid = -1;
467a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
468002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    pkgUid = mContext.getPackageManager().getPackageUid(packageName,
469002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                            UserHandle.getUserId(uid));
470002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                } catch (NameNotFoundException e) {
471a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
472002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                if (pkgUid != uid) {
473002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    // Oops!  The package name is not valid for the uid they are calling
474002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    // under.  Abort.
475002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    Slog.w(TAG, "Bad call: specified package " + packageName
476002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                            + " under uid " + uid + " but it is really " + pkgUid);
477002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    return null;
478002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                }
479002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            } finally {
480002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                Binder.restoreCallingIdentity(ident);
481a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
48235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            ops = new Ops(packageName, uid);
483a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps.put(packageName, ops);
484a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
48572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return ops;
48672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
48772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
4885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteLocked() {
4895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
4905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
4915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
4925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
4935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
4945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
4955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteNowLocked() {
4965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
4975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
4985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
4995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.removeCallbacks(mWriteRunner);
5005e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.post(mWriteRunner);
5015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
5025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
50372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
50472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        Ops ops = getOpsLocked(uid, packageName, edit);
50572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
50672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return null;
50772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
508f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        return getOpLocked(ops, code, edit);
509f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
510f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
511f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private Op getOpLocked(Ops ops, int code, boolean edit) {
512a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Op op = ops.get(code);
513a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (op == null) {
51435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
51535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
51635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
517a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = new Op(code);
518a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            ops.put(code, op);
519a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
5205e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (edit) {
5215e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            scheduleWriteLocked();
52235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
523a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return op;
524a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
525a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
52635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readState() {
52735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
52835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (this) {
52935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                FileInputStream stream;
53035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
53135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    stream = mFile.openRead();
53235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (FileNotFoundException e) {
53335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
53435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    return;
53535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
53635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                boolean success = false;
53735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
53835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    XmlPullParser parser = Xml.newPullParser();
53935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    parser.setInput(stream, null);
54035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int type;
54135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.START_TAG
54235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && type != XmlPullParser.END_DOCUMENT) {
54335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        ;
54435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
54535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
54635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (type != XmlPullParser.START_TAG) {
54735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        throw new IllegalStateException("no start tag found");
54835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
54935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
55035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int outerDepth = parser.getDepth();
55135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
55235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
55335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
55435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            continue;
55535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
55635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
55735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        String tagName = parser.getName();
55835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (tagName.equals("pkg")) {
55935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            readPackage(parser);
56035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        } else {
56135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Slog.w(TAG, "Unknown element under <app-ops>: "
56235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    + parser.getName());
56335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            XmlUtils.skipCurrentTag(parser);
56435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
56535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
56635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    success = true;
56735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IllegalStateException e) {
56835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
56935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NullPointerException e) {
57035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
57135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NumberFormatException e) {
57235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
57335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (XmlPullParserException e) {
57435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
57535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IOException e) {
57635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
57735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IndexOutOfBoundsException e) {
57835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
57935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } finally {
58035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (!success) {
58135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mUidOps.clear();
58235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
58335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    try {
58435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        stream.close();
58535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } catch (IOException e) {
58635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
58735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
58835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
58935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
59035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
59135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
59235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readPackage(XmlPullParser parser) throws NumberFormatException,
59335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
59435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        String pkgName = parser.getAttributeValue(null, "n");
59535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
59635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
59735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
59835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
59935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
60035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
60135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
60235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
60335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
60435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("uid")) {
60535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                readUid(parser, pkgName);
60635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
60735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
60835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
60935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
61035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
61135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
61235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
61335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
61435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
61535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
61635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
61735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
61835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
61935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
62035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
62135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
62235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
62335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
62435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
62535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
62635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("op")) {
62735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n")));
6285e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String mode = parser.getAttributeValue(null, "m");
6295e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (mode != null) {
6305e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.mode = Integer.parseInt(mode);
6315e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
6325e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String time = parser.getAttributeValue(null, "t");
6335e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
6345e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.time = Long.parseLong(time);
6355e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
6365e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                time = parser.getAttributeValue(null, "r");
6375e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
6385e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.rejectTime = Long.parseLong(time);
6395e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
6405e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String dur = parser.getAttributeValue(null, "d");
6415e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (dur != null) {
6425e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.duration = Integer.parseInt(dur);
6435e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
64435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.get(uid);
64535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (pkgOps == null) {
64635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps = new HashMap<String, Ops>();
64735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mUidOps.put(uid, pkgOps);
64835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
64935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Ops ops = pkgOps.get(pkgName);
65035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (ops == null) {
65135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ops = new Ops(pkgName, uid);
65235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps.put(pkgName, ops);
65335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
65435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                ops.put(op.op, op);
65535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
65635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
65735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
65835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
65935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
66035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
66135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
66235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
66335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void writeState() {
66435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
66535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
66635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
66735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            FileOutputStream stream;
66835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
66935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                stream = mFile.startWrite();
67035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
67135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state: " + e);
67235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return;
67335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
67435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
67535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
67635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlSerializer out = new FastXmlSerializer();
67735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.setOutput(stream, "utf-8");
67835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startDocument(null, true);
67935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startTag(null, "app-ops");
68035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
68135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (allOps != null) {
68235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    String lastPkg = null;
68335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    for (int i=0; i<allOps.size(); i++) {
68435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps pkg = allOps.get(i);
68535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (!pkg.getPackageName().equals(lastPkg)) {
68635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (lastPkg != null) {
68735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                out.endTag(null, "pkg");
68835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
68935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            lastPkg = pkg.getPackageName();
69035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "pkg");
69135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", lastPkg);
69235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
69335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.startTag(null, "uid");
69435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.attribute(null, "n", Integer.toString(pkg.getUid()));
69535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        List<AppOpsManager.OpEntry> ops = pkg.getOps();
69635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.size(); j++) {
69735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            AppOpsManager.OpEntry op = ops.get(j);
69835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "op");
69935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", Integer.toString(op.getOp()));
7005e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (op.getMode() != AppOpsManager.MODE_ALLOWED) {
7015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "m", Integer.toString(op.getMode()));
7025e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
7035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            long time = op.getTime();
7045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
7055e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "t", Long.toString(time));
7065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
7075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            time = op.getRejectTime();
7085e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
7095e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "r", Long.toString(time));
7105e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
7115e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            int dur = op.getDuration();
7125e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (dur != 0) {
7135e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "d", Integer.toString(dur));
7145e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
71535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.endTag(null, "op");
71635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
71735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "uid");
71835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
71935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (lastPkg != null) {
72035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "pkg");
72135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
72235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
72335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
72435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endTag(null, "app-ops");
72535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endDocument();
72635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.finishWrite(stream);
72735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
72835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state, restoring backup.", e);
72935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.failWrite(stream);
73035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
73135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
73235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
73335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
734a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
735a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
736a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
737a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
738a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Permission Denial: can't dump ApOps service from from pid="
739a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + Binder.getCallingPid()
740a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
741a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return;
742a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
743a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
744a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
745a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Current AppOps Service state:");
7465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            final long now = System.currentTimeMillis();
747a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
748a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
749a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
750a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                for (Ops ops : pkgOps.values()) {
751a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
752a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    for (int j=0; j<ops.size(); j++) {
753a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        Op op = ops.valueAt(j);
7545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
7555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print(": mode="); pw.print(op.mode);
7565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.time != 0) {
7575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
7585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
7595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
7605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.rejectTime != 0) {
7615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
7625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
7635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
764a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        if (op.duration == -1) {
765a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.println(" (running)");
766a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        } else {
767a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.print("; duration=");
768a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    TimeUtils.formatDuration(op.duration, pw);
769a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    pw.println();
770a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        }
771a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    }
772a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
773a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
774a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
775a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
776a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn}
777