AppOpsService.java revision e98f5dbe6b6f9f2cb6a73ee750faacda2596b34f
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;
43e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackbornimport android.util.ArrayMap;
44a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile;
455e45ee6752528791deb66b83d76250685de15d47Dianne Hackbornimport android.util.Log;
46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog;
47a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray;
48a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils;
4935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml;
50a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
51a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
52c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport com.android.internal.app.IAppOpsCallback;
5335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
5435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils;
5535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser;
5735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
5835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer;
59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub {
61a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    static final String TAG = "AppOps";
6235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final boolean DEBUG = false;
6335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
6435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    // Write at most every 30 minutes.
6535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
66a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
67a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    Context mContext;
68a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final AtomicFile mFile;
6935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Handler mHandler;
7035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    boolean mWriteScheduled;
7235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Runnable mWriteRunner = new Runnable() {
7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public void run() {
7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (AppOpsService.this) {
7535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    @Override protected Void doInBackground(Void... params) {
7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        writeState();
7935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        return null;
8035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
8135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                };
8235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
8335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
8435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
8535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    };
86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final SparseArray<HashMap<String, Ops>> mUidOps
88a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            = new SparseArray<HashMap<String, Ops>>();
89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
90c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Ops extends SparseArray<Op> {
91a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final String packageName;
9235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public final int uid;
93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
9435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public Ops(String _packageName, int _uid) {
95a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            packageName = _packageName;
9635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            uid = _uid;
97a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
100c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Op {
101e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public final int uid;
102e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public final String packageName;
103a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final int op;
1045e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public int mode;
105a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public int duration;
106a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public long time;
1075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public long rejectTime;
10835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public int nesting;
109a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
110e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public Op(int _uid, String _packageName, int _op) {
111e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            uid = _uid;
112e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            packageName = _packageName;
113a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = _op;
1145e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mode = AppOpsManager.MODE_ALLOWED;
115a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
116a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
117a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
118c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    final SparseArray<ArrayList<Callback>> mOpModeWatchers
119c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            = new SparseArray<ArrayList<Callback>>();
120e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers
121e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            = new ArrayMap<String, ArrayList<Callback>>();
122e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<IBinder, Callback> mModeWatchers
123e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            = new ArrayMap<IBinder, Callback>();
124c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
125c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final class Callback implements DeathRecipient {
126c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        final IAppOpsCallback mCallback;
127c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
128c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public Callback(IAppOpsCallback callback) {
129c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback = callback;
130c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            try {
131c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mCallback.asBinder().linkToDeath(this, 0);
132c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            } catch (RemoteException e) {
133c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
134c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
135c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
136c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void unlinkToDeath() {
137c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback.asBinder().unlinkToDeath(this, 0);
138c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
139c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
140c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        @Override
141c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void binderDied() {
142c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            stopWatchingMode(mCallback);
143c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
144c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
145c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
146e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>();
147e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
148e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public final class ClientState extends Binder implements DeathRecipient {
149e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final IBinder mAppToken;
150e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final int mPid;
151e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final ArrayList<Op> mStartedOps;
152e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
153e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public ClientState(IBinder appToken) {
154e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            mAppToken = appToken;
155e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            mPid = Binder.getCallingPid();
156e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (appToken instanceof Binder) {
157e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                // For local clients, there is no reason to track them.
158e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mStartedOps = null;
159e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            } else {
160e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mStartedOps = new ArrayList<Op>();
161e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                try {
162e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    mAppToken.linkToDeath(this, 0);
163e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                } catch (RemoteException e) {
164e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
165e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
166e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
167e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
168e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        @Override
169e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public String toString() {
170e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            return "ClientState{" +
171e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    "mAppToken=" + mAppToken +
172e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") +
173e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    '}';
174e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
175e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
176e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        @Override
177e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public void binderDied() {
178e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            synchronized (AppOpsService.this) {
179e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mStartedOps.size()-1; i>=0; i--) {
180e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    finishOperationLocked(mStartedOps.get(i));
181e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
182e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mClients.remove(mAppToken);
183e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
184e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
185e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
186e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
18735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public AppOpsService(File storagePath) {
18835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mFile = new AtomicFile(storagePath);
18935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mHandler = new Handler();
19035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        readState();
191a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
192a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
193a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void publish(Context context) {
194a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext = context;
195a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
196a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
197a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
198514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void systemReady() {
199514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
200514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            boolean changed = false;
201514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
202514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                HashMap<String, Ops> pkgs = mUidOps.valueAt(i);
203514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                Iterator<Ops> it = pkgs.values().iterator();
204514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                while (it.hasNext()) {
205514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    Ops ops = it.next();
206514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    int curUid;
207514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    try {
208514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        curUid = mContext.getPackageManager().getPackageUid(ops.packageName,
209514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                UserHandle.getUserId(ops.uid));
210514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    } catch (NameNotFoundException e) {
211514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        curUid = -1;
212514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
213514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (curUid != ops.uid) {
214514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        Slog.i(TAG, "Pruning old package " + ops.packageName
215514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                + "/" + ops.uid + ": new uid=" + curUid);
216514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        it.remove();
217514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        changed = true;
218514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
219514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
220514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                if (pkgs.size() <= 0) {
221514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    mUidOps.removeAt(i);
222514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
223514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
224514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (changed) {
225514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                scheduleWriteLocked();
226514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
227514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
228514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
229514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
230514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void packageRemoved(int uid, String packageName) {
231514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
232514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            HashMap<String, Ops> pkgs = mUidOps.get(uid);
233514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (pkgs != null) {
234514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                if (pkgs.remove(packageName) != null) {
235514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (pkgs.size() <= 0) {
236514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        mUidOps.remove(uid);
237514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
238514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    scheduleWriteLocked();
239514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
240514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
241514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
242514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
243514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
244514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void uidRemoved(int uid) {
245514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
246514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (mUidOps.indexOfKey(uid) >= 0) {
247514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                mUidOps.remove(uid);
248514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                scheduleWriteLocked();
249514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
250514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
251514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
252514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
253a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void shutdown() {
254a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Slog.w(TAG, "Writing app ops before shutdown...");
25535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        boolean doWrite = false;
25635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (this) {
25735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mWriteScheduled) {
25835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
25935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                doWrite = true;
26035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
26135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
26235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (doWrite) {
26335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            writeState();
26435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
265a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
266a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
26772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
26872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        ArrayList<AppOpsManager.OpEntry> resOps = null;
26972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
27072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            resOps = new ArrayList<AppOpsManager.OpEntry>();
27172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<pkgOps.size(); j++) {
27272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.valueAt(j);
2735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
2745e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        curOp.rejectTime, curOp.duration));
27572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
27672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        } else {
27772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<ops.length; j++) {
27872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.get(ops[j]);
27972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                if (curOp != null) {
28072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    if (resOps == null) {
28172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                        resOps = new ArrayList<AppOpsManager.OpEntry>();
28272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    }
2835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
2845e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            curOp.rejectTime, curOp.duration));
28572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                }
28672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
28772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
28872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return resOps;
28972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
29072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
291a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
29235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
29335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
29535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        ArrayList<AppOpsManager.PackageOps> res = null;
296a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
29735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
29835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> packages = mUidOps.valueAt(i);
29935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                for (Ops pkgOps : packages.values()) {
30072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
30135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (resOps != null) {
30235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (res == null) {
30335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            res = new ArrayList<AppOpsManager.PackageOps>();
30435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
30535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
30635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                pkgOps.packageName, pkgOps.uid, resOps);
30735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        res.add(resPackage);
30835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
30935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
310a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
311a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
31235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return res;
313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
314a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
315a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
31672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
31772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            int[] ops) {
31872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
31972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
32072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        synchronized (this) {
32172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            Ops pkgOps = getOpsLocked(uid, packageName, false);
32272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (pkgOps == null) {
32372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
32472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
32572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
32672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (resOps == null) {
32772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
32872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
32972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
33072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
33172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    pkgOps.packageName, pkgOps.uid, resOps);
33272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            res.add(resPackage);
33372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return res;
33472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
33572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
33672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
33772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    @Override
3385e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public void setMode(int code, int uid, String packageName, int mode) {
339f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
340961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
341c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        ArrayList<Callback> repCbs = null;
342c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        code = AppOpsManager.opToSwitch(code);
3435e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        synchronized (this) {
344c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
3455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (op != null) {
3465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (op.mode != mode) {
3475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.mode = mode;
348c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.get(code);
349c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
350c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
351c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
352c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
353c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
354c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
355c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = mPackageModeWatchers.get(packageName);
356c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
357c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
358c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
359c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
360c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
361c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
362514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (mode == AppOpsManager.MODE_ALLOWED) {
363514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // If going into the default mode, prune this op
364514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // if there is nothing else interesting in it.
365514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        if (op.time == 0 && op.rejectTime == 0) {
366514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                            Ops ops = getOpsLocked(uid, packageName, false);
367514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                            if (ops != null) {
368514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                ops.remove(op.op);
369514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                if (ops.size() <= 0) {
370514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                    HashMap<String, Ops> pkgOps = mUidOps.get(uid);
371514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                    if (pkgOps != null) {
372514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                        pkgOps.remove(ops.packageName);
373514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                        if (pkgOps.size() <= 0) {
374514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                            mUidOps.remove(uid);
375514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                        }
376514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                    }
377514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                }
378514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                            }
379514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        }
380514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
3815e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    scheduleWriteNowLocked();
3825e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
3835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
3845e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
385c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        if (repCbs != null) {
386c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            for (int i=0; i<repCbs.size(); i++) {
387c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                try {
388c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    repCbs.get(i).mCallback.opChanged(code, packageName);
389c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                } catch (RemoteException e) {
390c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
391c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
392c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
393c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
394c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
395c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
396c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
397c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
398c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            op = AppOpsManager.opToSwitch(op);
399c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.get(callback.asBinder());
400c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb == null) {
401c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb = new Callback(callback);
402c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mModeWatchers.put(callback.asBinder(), cb);
403c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
404c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (op != AppOpsManager.OP_NONE) {
405c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mOpModeWatchers.get(op);
406c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
407c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
408c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mOpModeWatchers.put(op, cbs);
409c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
410c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
411c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
412c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (packageName != null) {
413c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
414c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
415c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
416c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mPackageModeWatchers.put(packageName, cbs);
417c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
418c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
419c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
420c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
421c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
422c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
423c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
424c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void stopWatchingMode(IAppOpsCallback callback) {
425c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
426c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.remove(callback.asBinder());
427c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb != null) {
428c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb.unlinkToDeath();
429e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
430c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
431c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs.remove(cb);
432c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs.size() <= 0) {
433c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        mOpModeWatchers.removeAt(i);
434c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
435c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
436e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
437e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i);
438e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    cbs.remove(cb);
439e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cbs.size() <= 0) {
440e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        mPackageModeWatchers.removeAt(i);
441c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
442c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
443c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
444c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
4455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
4465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
4475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    @Override
448e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public IBinder getToken(IBinder clientToken) {
449e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        synchronized (this) {
450e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            ClientState cs = mClients.get(clientToken);
451e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (cs == null) {
452e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                cs = new ClientState(clientToken);
453e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mClients.put(clientToken, cs);
454e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
455e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            return cs;
456e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
457e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
458e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
459e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    @Override
46035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int checkOperation(int code, int uid, String packageName) {
461f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
462961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
463a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
464f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
465a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
46635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_ALLOWED;
467a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
4685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return op.mode;
469a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
470a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
471a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
472a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
47335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int noteOperation(int code, int uid, String packageName) {
474f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
475961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
476a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
477f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
478f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
4795e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
4805e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
48135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_IGNORED;
482a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
483f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
48435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.duration == -1) {
48535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
486a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
487a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
48835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.duration = 0;
489f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
490f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
491f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
492f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
493f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
4945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
495f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
4965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
4975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
4985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
4995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            op.time = System.currentTimeMillis();
500514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            op.rejectTime = 0;
5015e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
502a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
503a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
504a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
505a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
506e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public int startOperation(IBinder token, int code, int uid, String packageName) {
507f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
508961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
509e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
510a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
511f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
512f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
5135e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
5145e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
515a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return AppOpsManager.MODE_IGNORED;
516a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
517f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
518f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
519f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
520f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
521f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
522f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
5235e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
524f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
5255e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
5265e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
5275e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
52835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting == 0) {
52935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = System.currentTimeMillis();
530514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                op.rejectTime = 0;
53135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = -1;
532a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
53335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.nesting++;
534e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
535e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                client.mStartedOps.add(op);
536e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
5375e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
539a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
540a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
541a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
542e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public void finishOperation(IBinder token, int code, int uid, String packageName) {
543f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
544961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
545e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
546a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
54735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
548a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
549a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
550a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
551e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
552e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                if (!client.mStartedOps.remove(op)) {
553e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    throw new IllegalStateException("Operation not started: uid" + op.uid
554e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            + " pkg=" + op.packageName + " op=" + op.op);
55535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
556e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
557e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            finishOperationLocked(op);
558e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
559e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
560e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
561e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    void finishOperationLocked(Op op) {
562e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        if (op.nesting <= 1) {
563e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (op.nesting == 1) {
564e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.duration = (int)(System.currentTimeMillis() - op.time);
565e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.time += op.duration;
56635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
567e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg "
568e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + op.packageName + " code " + op.op + " time=" + op.time
569e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + " duration=" + op.duration + " nesting=" + op.nesting);
570a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
571e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting = 0;
572e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        } else {
573e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting--;
574a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
575a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
576a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
577f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
578a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (uid == Binder.getCallingUid()) {
579f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
580a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
581a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
582f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
583a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
584a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
585a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
586a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
587a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
588961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    private void verifyIncomingOp(int op) {
589961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        if (op >= 0 && op < AppOpsManager._NUM_OP) {
590961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn            return;
591961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        }
592961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        throw new IllegalArgumentException("Bad operation #" + op);
593961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    }
594961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn
59572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
596a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        HashMap<String, Ops> pkgOps = mUidOps.get(uid);
597a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (pkgOps == null) {
59835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
59935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
60035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
601a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps = new HashMap<String, Ops>();
602a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mUidOps.put(uid, pkgOps);
603a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
604514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        if (uid == 0) {
605514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "root";
606514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        } else if (uid == Process.SHELL_UID) {
607514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "com.android.shell";
608514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
609a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Ops ops = pkgOps.get(packageName);
610a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (ops == null) {
61135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
61235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
61335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
614a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // This is the first time we have seen this package name under this uid,
615a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // so let's make sure it is valid.
616514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (uid != 0) {
617514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                final long ident = Binder.clearCallingIdentity();
618a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
619514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    int pkgUid = -1;
620514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    try {
621514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        pkgUid = mContext.getPackageManager().getPackageUid(packageName,
622514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                UserHandle.getUserId(uid));
623514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    } catch (NameNotFoundException e) {
624713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        if ("media".equals(packageName)) {
625713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                            pkgUid = Process.MEDIA_UID;
626713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        }
627514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
628514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (pkgUid != uid) {
629514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // Oops!  The package name is not valid for the uid they are calling
630514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // under.  Abort.
631514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        Slog.w(TAG, "Bad call: specified package " + packageName
632514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                + " under uid " + uid + " but it is really " + pkgUid);
633514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        return null;
634514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
635514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                } finally {
636514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    Binder.restoreCallingIdentity(ident);
637002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                }
638a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
63935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            ops = new Ops(packageName, uid);
640a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps.put(packageName, ops);
641a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
64272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return ops;
64372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
64472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
6455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteLocked() {
6465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
6475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
6485e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
6495e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
6505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
6515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
6525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteNowLocked() {
6535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
6545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
6555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
6565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.removeCallbacks(mWriteRunner);
6575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.post(mWriteRunner);
6585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
6595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
66072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
66172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        Ops ops = getOpsLocked(uid, packageName, edit);
66272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
66372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return null;
66472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
665f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        return getOpLocked(ops, code, edit);
666f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
667f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
668f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private Op getOpLocked(Ops ops, int code, boolean edit) {
669a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Op op = ops.get(code);
670a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (op == null) {
67135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
67235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
67335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
674e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op = new Op(ops.uid, ops.packageName, code);
675a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            ops.put(code, op);
676a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
6775e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (edit) {
6785e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            scheduleWriteLocked();
67935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
680a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return op;
681a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
682a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
68335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readState() {
68435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
68535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (this) {
68635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                FileInputStream stream;
68735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
68835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    stream = mFile.openRead();
68935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (FileNotFoundException e) {
69035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
69135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    return;
69235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
69335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                boolean success = false;
69435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
69535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    XmlPullParser parser = Xml.newPullParser();
69635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    parser.setInput(stream, null);
69735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int type;
69835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.START_TAG
69935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && type != XmlPullParser.END_DOCUMENT) {
70035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        ;
70135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
70235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
70335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (type != XmlPullParser.START_TAG) {
70435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        throw new IllegalStateException("no start tag found");
70535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
70635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
70735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int outerDepth = parser.getDepth();
70835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
70935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
71035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
71135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            continue;
71235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
71335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
71435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        String tagName = parser.getName();
71535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (tagName.equals("pkg")) {
71635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            readPackage(parser);
71735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        } else {
71835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Slog.w(TAG, "Unknown element under <app-ops>: "
71935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    + parser.getName());
72035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            XmlUtils.skipCurrentTag(parser);
72135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
72235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
72335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    success = true;
72435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IllegalStateException e) {
72535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
72635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NullPointerException e) {
72735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
72835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NumberFormatException e) {
72935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
73035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (XmlPullParserException e) {
73135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
73235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IOException e) {
73335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
73435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IndexOutOfBoundsException e) {
73535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
73635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } finally {
73735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (!success) {
73835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mUidOps.clear();
73935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
74035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    try {
74135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        stream.close();
74235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } catch (IOException e) {
74335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
74435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
74535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
74635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
74735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
74835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
74935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readPackage(XmlPullParser parser) throws NumberFormatException,
75035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
75135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        String pkgName = parser.getAttributeValue(null, "n");
75235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
75335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
75435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
75535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
75635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
75735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
75835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
75935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
76035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
76135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("uid")) {
76235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                readUid(parser, pkgName);
76335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
76435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
76535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
76635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
76735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
76835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
76935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
77035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
77135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
77235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
77335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
77435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
77535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
77635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
77735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
77835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
77935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
78035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
78135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
78235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
78335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("op")) {
784e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n")));
7855e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String mode = parser.getAttributeValue(null, "m");
7865e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (mode != null) {
7875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.mode = Integer.parseInt(mode);
7885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
7895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String time = parser.getAttributeValue(null, "t");
7905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
7915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.time = Long.parseLong(time);
7925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
7935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                time = parser.getAttributeValue(null, "r");
7945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
7955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.rejectTime = Long.parseLong(time);
7965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
7975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String dur = parser.getAttributeValue(null, "d");
7985e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (dur != null) {
7995e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.duration = Integer.parseInt(dur);
8005e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
80135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.get(uid);
80235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (pkgOps == null) {
80335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps = new HashMap<String, Ops>();
80435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mUidOps.put(uid, pkgOps);
80535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
80635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Ops ops = pkgOps.get(pkgName);
80735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (ops == null) {
80835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ops = new Ops(pkgName, uid);
80935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps.put(pkgName, ops);
81035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
81135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                ops.put(op.op, op);
81235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
81335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
81435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
81535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
81635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
81735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
81835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
81935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
82035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void writeState() {
82135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
82235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
82335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
82435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            FileOutputStream stream;
82535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
82635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                stream = mFile.startWrite();
82735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
82835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state: " + e);
82935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return;
83035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
83135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
83235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
83335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlSerializer out = new FastXmlSerializer();
83435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.setOutput(stream, "utf-8");
83535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startDocument(null, true);
83635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startTag(null, "app-ops");
83735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
83835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (allOps != null) {
83935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    String lastPkg = null;
84035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    for (int i=0; i<allOps.size(); i++) {
84135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps pkg = allOps.get(i);
84235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (!pkg.getPackageName().equals(lastPkg)) {
84335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (lastPkg != null) {
84435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                out.endTag(null, "pkg");
84535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
84635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            lastPkg = pkg.getPackageName();
84735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "pkg");
84835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", lastPkg);
84935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
85035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.startTag(null, "uid");
85135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.attribute(null, "n", Integer.toString(pkg.getUid()));
85235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        List<AppOpsManager.OpEntry> ops = pkg.getOps();
85335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.size(); j++) {
85435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            AppOpsManager.OpEntry op = ops.get(j);
85535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "op");
85635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", Integer.toString(op.getOp()));
8575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (op.getMode() != AppOpsManager.MODE_ALLOWED) {
8585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "m", Integer.toString(op.getMode()));
8595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
8605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            long time = op.getTime();
8615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
8625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "t", Long.toString(time));
8635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
8645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            time = op.getRejectTime();
8655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
8665e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "r", Long.toString(time));
8675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
8685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            int dur = op.getDuration();
8695e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (dur != 0) {
8705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "d", Integer.toString(dur));
8715e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
87235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.endTag(null, "op");
87335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
87435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "uid");
87535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
87635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (lastPkg != null) {
87735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "pkg");
87835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
87935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
88035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
88135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endTag(null, "app-ops");
88235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endDocument();
88335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.finishWrite(stream);
88435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
88535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state, restoring backup.", e);
88635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.failWrite(stream);
88735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
88835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
88935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
89035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
891a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
892a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
893a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
894a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
895a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Permission Denial: can't dump ApOps service from from pid="
896a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + Binder.getCallingPid()
897a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
898a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return;
899a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
900a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
901a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
902a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Current AppOps Service state:");
9035e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            final long now = System.currentTimeMillis();
904e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            boolean needSep = false;
905e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mOpModeWatchers.size() > 0) {
906e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
907e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Op mode watchers:");
908e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mOpModeWatchers.size(); i++) {
909e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
910e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
911e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i);
912e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
913e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
914e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
915e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
916e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
917e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
918e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mPackageModeWatchers.size() > 0) {
919e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
920e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Package mode watchers:");
921e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mPackageModeWatchers.size(); i++) {
922e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
923e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
924e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i);
925e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
926e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
927e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
928e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
929e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
930e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
931e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mModeWatchers.size() > 0) {
932e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
933e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  All mode watchers:");
934e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mModeWatchers.size(); i++) {
935e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mModeWatchers.keyAt(i));
936e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print(" -> "); pw.println(mModeWatchers.valueAt(i));
937e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
938e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
939e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mClients.size() > 0) {
940e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
941e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Clients:");
942e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mClients.size(); i++) {
943e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mClients.keyAt(i)); pw.println(":");
944e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ClientState cs = mClients.valueAt(i);
945e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("      "); pw.println(cs);
946e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) {
947e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println("      Started ops:");
948e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        for (int j=0; j<cs.mStartedOps.size(); j++) {
949e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            Op op = cs.mStartedOps.get(j);
950e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print("        "); pw.print("uid="); pw.print(op.uid);
951e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" pkg="); pw.print(op.packageName);
952e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
953e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        }
954e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
955e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
956e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
957e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (needSep) {
958e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println();
959e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
960a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
961a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
962a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
963a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                for (Ops ops : pkgOps.values()) {
964a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
965a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    for (int j=0; j<ops.size(); j++) {
966a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        Op op = ops.valueAt(j);
9675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
9685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print(": mode="); pw.print(op.mode);
9695e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.time != 0) {
9705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
9715e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
9725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
9735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.rejectTime != 0) {
9745e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
9755e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
9765e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
977a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        if (op.duration == -1) {
978a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.println(" (running)");
979a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        } else {
980a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.print("; duration=");
981a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    TimeUtils.formatDuration(op.duration, pw);
982a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    pw.println();
983a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        }
984a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    }
985a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
986a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
987a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
988a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
989a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn}
990