AppOpsService.java revision f5d831915dd11e77cdcf5669228c55fe17a21c5e
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;
30607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackbornimport java.util.Map;
31a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
32a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
33a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.Context;
34a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager;
35a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
3635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.AsyncTask;
37a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Binder;
3835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.Handler;
39c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.IBinder;
40a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Process;
41c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport android.os.RemoteException;
42a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager;
43a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.UserHandle;
44e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackbornimport android.util.ArrayMap;
45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile;
465e45ee6752528791deb66b83d76250685de15d47Dianne Hackbornimport android.util.Log;
47607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackbornimport android.util.Pair;
48a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog;
49a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray;
50a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils;
5135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml;
52a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
53a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
54c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackbornimport com.android.internal.app.IAppOpsCallback;
5535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils;
5735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
5835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser;
5935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
6035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer;
61a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub {
63a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    static final String TAG = "AppOps";
6435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final boolean DEBUG = false;
6535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
6635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    // Write at most every 30 minutes.
6735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
68a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
69a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    Context mContext;
70a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final AtomicFile mFile;
7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Handler mHandler;
7235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    boolean mWriteScheduled;
7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Runnable mWriteRunner = new Runnable() {
7535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public void run() {
7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (AppOpsService.this) {
7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
7935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    @Override protected Void doInBackground(Void... params) {
8035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        writeState();
8135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        return null;
8235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
8335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                };
8435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
8535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
8635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
8735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    };
88a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final SparseArray<HashMap<String, Ops>> mUidOps
90a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            = new SparseArray<HashMap<String, Ops>>();
91a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
92c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Ops extends SparseArray<Op> {
93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final String packageName;
9435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public final int uid;
95a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
9635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public Ops(String _packageName, int _uid) {
97a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            packageName = _packageName;
9835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            uid = _uid;
99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
100a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
102c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final static class Op {
103e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public final int uid;
104e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public final String packageName;
105a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final int op;
1065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public int mode;
107a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public int duration;
108a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public long time;
1095e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        public long rejectTime;
11035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public int nesting;
111a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
112e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public Op(int _uid, String _packageName, int _op) {
113e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            uid = _uid;
114e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            packageName = _packageName;
115a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = _op;
116f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun            mode = AppOpsManager.opToDefaultMode(op);
117a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
118a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
119a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
120c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    final SparseArray<ArrayList<Callback>> mOpModeWatchers
121c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            = new SparseArray<ArrayList<Callback>>();
122e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<String, ArrayList<Callback>> mPackageModeWatchers
123e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            = new ArrayMap<String, ArrayList<Callback>>();
124e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<IBinder, Callback> mModeWatchers
125e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            = new ArrayMap<IBinder, Callback>();
126c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
127c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public final class Callback implements DeathRecipient {
128c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        final IAppOpsCallback mCallback;
129c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
130c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public Callback(IAppOpsCallback callback) {
131c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback = callback;
132c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            try {
133c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mCallback.asBinder().linkToDeath(this, 0);
134c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            } catch (RemoteException e) {
135c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
136c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
137c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
138c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void unlinkToDeath() {
139c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            mCallback.asBinder().unlinkToDeath(this, 0);
140c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
141c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
142c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        @Override
143c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        public void binderDied() {
144c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            stopWatchingMode(mCallback);
145c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
146c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
147c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
148e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    final ArrayMap<IBinder, ClientState> mClients = new ArrayMap<IBinder, ClientState>();
149e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
150e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public final class ClientState extends Binder implements DeathRecipient {
151e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final IBinder mAppToken;
152e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final int mPid;
153e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        final ArrayList<Op> mStartedOps;
154e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
155e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public ClientState(IBinder appToken) {
156e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            mAppToken = appToken;
157e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            mPid = Binder.getCallingPid();
158e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (appToken instanceof Binder) {
159e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                // For local clients, there is no reason to track them.
160e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mStartedOps = null;
161e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            } else {
162e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mStartedOps = new ArrayList<Op>();
163e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                try {
164e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    mAppToken.linkToDeath(this, 0);
165e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                } catch (RemoteException e) {
166e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
167e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
168e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
169e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
170e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        @Override
171e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public String toString() {
172e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            return "ClientState{" +
173e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    "mAppToken=" + mAppToken +
174e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ", " + (mStartedOps != null ? ("pid=" + mPid) : "local") +
175e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    '}';
176e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
177e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
178e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        @Override
179e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        public void binderDied() {
180e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            synchronized (AppOpsService.this) {
181e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mStartedOps.size()-1; i>=0; i--) {
182e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    finishOperationLocked(mStartedOps.get(i));
183e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
184e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mClients.remove(mAppToken);
185e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
186e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
187e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
188e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
18935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public AppOpsService(File storagePath) {
19035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mFile = new AtomicFile(storagePath);
19135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mHandler = new Handler();
19235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        readState();
193a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
194f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun
195a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void publish(Context context) {
196a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext = context;
197a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
198a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
199a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
200514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void systemReady() {
201514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
202514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            boolean changed = false;
203514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
204514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                HashMap<String, Ops> pkgs = mUidOps.valueAt(i);
205514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                Iterator<Ops> it = pkgs.values().iterator();
206514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                while (it.hasNext()) {
207514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    Ops ops = it.next();
208514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    int curUid;
209514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    try {
210514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        curUid = mContext.getPackageManager().getPackageUid(ops.packageName,
211514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                UserHandle.getUserId(ops.uid));
212514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    } catch (NameNotFoundException e) {
213514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        curUid = -1;
214514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
215514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (curUid != ops.uid) {
216514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        Slog.i(TAG, "Pruning old package " + ops.packageName
217514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                + "/" + ops.uid + ": new uid=" + curUid);
218514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        it.remove();
219514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        changed = true;
220514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
221514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
222514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                if (pkgs.size() <= 0) {
223514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    mUidOps.removeAt(i);
224514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
225514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
226514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (changed) {
227514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                scheduleWriteLocked();
228514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
229514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
230514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
231514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
232514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void packageRemoved(int uid, String packageName) {
233514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
234514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            HashMap<String, Ops> pkgs = mUidOps.get(uid);
235514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (pkgs != null) {
236514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                if (pkgs.remove(packageName) != null) {
237514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (pkgs.size() <= 0) {
238514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        mUidOps.remove(uid);
239514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
240514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    scheduleWriteLocked();
241514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                }
242514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
243514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
244514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
245514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
246514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    public void uidRemoved(int uid) {
247514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        synchronized (this) {
248514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (mUidOps.indexOfKey(uid) >= 0) {
249514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                mUidOps.remove(uid);
250514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                scheduleWriteLocked();
251514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            }
252514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
253514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn    }
254514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn
255a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void shutdown() {
256a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Slog.w(TAG, "Writing app ops before shutdown...");
25735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        boolean doWrite = false;
25835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (this) {
25935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mWriteScheduled) {
26035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
26135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                doWrite = true;
26235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
26335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
26435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (doWrite) {
26535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            writeState();
26635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
267a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
268a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
26972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private ArrayList<AppOpsManager.OpEntry> collectOps(Ops pkgOps, int[] ops) {
27072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        ArrayList<AppOpsManager.OpEntry> resOps = null;
27172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
27272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            resOps = new ArrayList<AppOpsManager.OpEntry>();
27372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<pkgOps.size(); j++) {
27472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.valueAt(j);
2755e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
2765e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        curOp.rejectTime, curOp.duration));
27772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
27872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        } else {
27972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            for (int j=0; j<ops.length; j++) {
28072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Op curOp = pkgOps.get(ops[j]);
28172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                if (curOp != null) {
28272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    if (resOps == null) {
28372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                        resOps = new ArrayList<AppOpsManager.OpEntry>();
28472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    }
2855e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.mode, curOp.time,
2865e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            curOp.rejectTime, curOp.duration));
28772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                }
28872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
28972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
29072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return resOps;
29172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
29272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
293a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
29535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
29635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
29735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        ArrayList<AppOpsManager.PackageOps> res = null;
298a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
29935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
30035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> packages = mUidOps.valueAt(i);
30135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                for (Ops pkgOps : packages.values()) {
30272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
30335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (resOps != null) {
30435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (res == null) {
30535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            res = new ArrayList<AppOpsManager.PackageOps>();
30635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
30735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
30835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                pkgOps.packageName, pkgOps.uid, resOps);
30935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        res.add(resPackage);
31035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
31135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
312a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
31435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return res;
315a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
316a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
317a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
31872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    public List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName,
31972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            int[] ops) {
32072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
32172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
32272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        synchronized (this) {
32372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            Ops pkgOps = getOpsLocked(uid, packageName, false);
32472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (pkgOps == null) {
32572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
32672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
32772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(pkgOps, ops);
32872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            if (resOps == null) {
32972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                return null;
33072e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            }
33172e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
33272e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
33372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn                    pkgOps.packageName, pkgOps.uid, resOps);
33472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            res.add(resPackage);
33572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return res;
33672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
33772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
33872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
339607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    private void pruneOp(Op op, int uid, String packageName) {
340607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        if (op.time == 0 && op.rejectTime == 0) {
341607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            Ops ops = getOpsLocked(uid, packageName, false);
342607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            if (ops != null) {
343607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                ops.remove(op.op);
344607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                if (ops.size() <= 0) {
345607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    HashMap<String, Ops> pkgOps = mUidOps.get(uid);
346607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    if (pkgOps != null) {
347607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        pkgOps.remove(ops.packageName);
348607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        if (pkgOps.size() <= 0) {
349607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            mUidOps.remove(uid);
350607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        }
351607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    }
352607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                }
353607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
354607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
355607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    }
356607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn
35772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    @Override
3585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    public void setMode(int code, int uid, String packageName, int mode) {
359f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
360961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
361c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        ArrayList<Callback> repCbs = null;
362c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        code = AppOpsManager.opToSwitch(code);
3635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        synchronized (this) {
364c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
3655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (op != null) {
3665e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (op.mode != mode) {
3675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.mode = mode;
368c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.get(code);
369c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
370c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
371c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
372c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
373c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
374c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
375c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = mPackageModeWatchers.get(packageName);
376c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs != null) {
377c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        if (repCbs == null) {
378c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                            repCbs = new ArrayList<Callback>();
379c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        }
380c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        repCbs.addAll(cbs);
381c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
382f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                    if (mode == AppOpsManager.opToDefaultMode(op.op)) {
383514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // If going into the default mode, prune this op
384514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // if there is nothing else interesting in it.
385607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        pruneOp(op, uid, packageName);
386514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
3875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    scheduleWriteNowLocked();
3885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
3895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
3905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
391c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        if (repCbs != null) {
392c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            for (int i=0; i<repCbs.size(); i++) {
393c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                try {
394c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    repCbs.get(i).mCallback.opChanged(code, packageName);
395c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                } catch (RemoteException e) {
396c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
397c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
398c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
399c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
400c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
401607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    private static HashMap<Callback, ArrayList<Pair<String, Integer>>> addCallbacks(
402607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks,
403607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            String packageName, int op, ArrayList<Callback> cbs) {
404607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        if (cbs == null) {
405607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            return callbacks;
406607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
407607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        if (callbacks == null) {
408607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            callbacks = new HashMap<Callback, ArrayList<Pair<String, Integer>>>();
409607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
410607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        for (int i=0; i<cbs.size(); i++) {
411607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            Callback cb = cbs.get(i);
412607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            ArrayList<Pair<String, Integer>> reports = callbacks.get(cb);
413607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            if (reports == null) {
414607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                reports = new ArrayList<Pair<String, Integer>>();
415607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                callbacks.put(cb, reports);
416607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
417607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            reports.add(new Pair<String, Integer>(packageName, op));
418607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
419607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        return callbacks;
420607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    }
421607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn
422607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    @Override
423607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    public void resetAllModes() {
424607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
425607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
426607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null;
427607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        synchronized (this) {
428607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            boolean changed = false;
4297f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn            for (int i=mUidOps.size()-1; i>=0; i--) {
430607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                HashMap<String, Ops> packages = mUidOps.valueAt(i);
4317f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
4327f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                while (it.hasNext()) {
4337f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    Map.Entry<String, Ops> ent = it.next();
434607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    String packageName = ent.getKey();
435607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    Ops pkgOps = ent.getValue();
4367f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    for (int j=pkgOps.size()-1; j>=0; j--) {
437607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        Op curOp = pkgOps.valueAt(j);
438f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                        if (curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
439f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                            curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
440607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            changed = true;
441607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
442607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                                    mOpModeWatchers.get(curOp.op));
443607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
444607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                                    mPackageModeWatchers.get(packageName));
4457f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                            if (curOp.time == 0 && curOp.rejectTime == 0) {
4467f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                                pkgOps.removeAt(j);
4477f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                            }
448607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        }
449607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    }
4507f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    if (pkgOps.size() == 0) {
4517f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                        it.remove();
4527f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    }
4537f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                }
4547f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                if (packages.size() == 0) {
4557f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    mUidOps.removeAt(i);
456607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                }
457607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
458607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            if (changed) {
459607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                scheduleWriteNowLocked();
460607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
461607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
462607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        if (callbacks != null) {
463607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            for (Map.Entry<Callback, ArrayList<Pair<String, Integer>>> ent : callbacks.entrySet()) {
464607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                Callback cb = ent.getKey();
465607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                ArrayList<Pair<String, Integer>> reports = ent.getValue();
466607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                for (int i=0; i<reports.size(); i++) {
467607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    Pair<String, Integer> rep = reports.get(i);
468607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    try {
469607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        cb.mCallback.opChanged(rep.second, rep.first);
470607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    } catch (RemoteException e) {
471607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    }
472607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                }
473607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
474607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
475607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    }
476607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn
477c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
478c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
479c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
480c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            op = AppOpsManager.opToSwitch(op);
481c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.get(callback.asBinder());
482c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb == null) {
483c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb = new Callback(callback);
484c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mModeWatchers.put(callback.asBinder(), cb);
485c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
486c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (op != AppOpsManager.OP_NONE) {
487c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mOpModeWatchers.get(op);
488c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
489c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
490c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mOpModeWatchers.put(op, cbs);
491c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
492c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
493c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
494c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (packageName != null) {
495c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
496c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
497c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
498c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mPackageModeWatchers.put(packageName, cbs);
499c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
500c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
501c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
502c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
503c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
504c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
505c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
506c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void stopWatchingMode(IAppOpsCallback callback) {
507c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
508c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.remove(callback.asBinder());
509c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb != null) {
510c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb.unlinkToDeath();
511e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
512c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
513c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs.remove(cb);
514c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs.size() <= 0) {
515c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        mOpModeWatchers.removeAt(i);
516c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
517c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
518e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
519e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i);
520e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    cbs.remove(cb);
521e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cbs.size() <= 0) {
522e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        mPackageModeWatchers.removeAt(i);
523c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
524c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
525c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
526c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
5275e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
5285e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
5295e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    @Override
530e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public IBinder getToken(IBinder clientToken) {
531e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        synchronized (this) {
532e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            ClientState cs = mClients.get(clientToken);
533e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (cs == null) {
534e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                cs = new ClientState(clientToken);
535e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mClients.put(clientToken, cs);
536e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
537e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            return cs;
538e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
540e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
541e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    @Override
54235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int checkOperation(int code, int uid, String packageName) {
543f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
544961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
546f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
547a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
548f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                return AppOpsManager.opToDefaultMode(code);
549a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
5505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return op.mode;
551a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
552a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
553a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
554a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
555911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    public int checkPackage(int uid, String packageName) {
556911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey        synchronized (this) {
557911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            if (getOpsLocked(uid, packageName, true) != null) {
558911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ALLOWED;
559911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            } else {
560911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
561911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            }
562911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey        }
563911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    }
564911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey
565911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    @Override
56635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int noteOperation(int code, int uid, String packageName) {
567f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
568961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
569a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
570f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
571f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
5725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
5735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
574911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
575a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
576f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
57735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.duration == -1) {
57835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
579a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
580a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
58135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.duration = 0;
582f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
583f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
584f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
585f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
586f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
5875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
588f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
5895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
5905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
5915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
5925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            op.time = System.currentTimeMillis();
593514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            op.rejectTime = 0;
5945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
595a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
596a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
597a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
598a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
599e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public int startOperation(IBinder token, int code, int uid, String packageName) {
600f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
601961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
602e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
603a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
604f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
605f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
6065e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
6075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
608911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
609a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
610f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
611f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
612f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
613f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
614f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
615f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
6165e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
617f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
6185e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
6195e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
6205e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
62135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting == 0) {
62235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = System.currentTimeMillis();
623514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                op.rejectTime = 0;
62435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = -1;
625a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
62635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.nesting++;
627e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
628e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                client.mStartedOps.add(op);
629e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
6305e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
631a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
632a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
633a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
634a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
635e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public void finishOperation(IBinder token, int code, int uid, String packageName) {
636f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
637961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
638e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
639a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
64035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
641a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
642a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
643a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
644e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
645e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                if (!client.mStartedOps.remove(op)) {
646e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    throw new IllegalStateException("Operation not started: uid" + op.uid
647e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            + " pkg=" + op.packageName + " op=" + op.op);
64835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
649e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
650e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            finishOperationLocked(op);
651e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
652e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
653e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
654e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    void finishOperationLocked(Op op) {
655e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        if (op.nesting <= 1) {
656e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (op.nesting == 1) {
657e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.duration = (int)(System.currentTimeMillis() - op.time);
658e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.time += op.duration;
65935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
660e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg "
661e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + op.packageName + " code " + op.op + " time=" + op.time
662e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + " duration=" + op.duration + " nesting=" + op.nesting);
663a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
664e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting = 0;
665e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        } else {
666e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting--;
667a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
668a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
669a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
670f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
671a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (uid == Binder.getCallingUid()) {
672f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
673a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
674a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
675f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
676a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
677a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
678a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
679a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
680a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
681961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    private void verifyIncomingOp(int op) {
682961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        if (op >= 0 && op < AppOpsManager._NUM_OP) {
683961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn            return;
684961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        }
685961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        throw new IllegalArgumentException("Bad operation #" + op);
686961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    }
687961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn
68872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
689a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        HashMap<String, Ops> pkgOps = mUidOps.get(uid);
690a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (pkgOps == null) {
69135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
69235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
69335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
694a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps = new HashMap<String, Ops>();
695a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mUidOps.put(uid, pkgOps);
696a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
697514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        if (uid == 0) {
698514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "root";
699514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        } else if (uid == Process.SHELL_UID) {
700514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "com.android.shell";
701514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
702a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Ops ops = pkgOps.get(packageName);
703a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (ops == null) {
70435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
70535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
70635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
707a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // This is the first time we have seen this package name under this uid,
708a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // so let's make sure it is valid.
709514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (uid != 0) {
710514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                final long ident = Binder.clearCallingIdentity();
711a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
712514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    int pkgUid = -1;
713514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    try {
714514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        pkgUid = mContext.getPackageManager().getPackageUid(packageName,
715514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                UserHandle.getUserId(uid));
716514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    } catch (NameNotFoundException e) {
717713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        if ("media".equals(packageName)) {
718713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                            pkgUid = Process.MEDIA_UID;
719713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        }
720514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
721514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (pkgUid != uid) {
722514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // Oops!  The package name is not valid for the uid they are calling
723514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // under.  Abort.
724514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        Slog.w(TAG, "Bad call: specified package " + packageName
725514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                + " under uid " + uid + " but it is really " + pkgUid);
726514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        return null;
727514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
728514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                } finally {
729514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    Binder.restoreCallingIdentity(ident);
730002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                }
731a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
73235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            ops = new Ops(packageName, uid);
733a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps.put(packageName, ops);
734a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
73572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return ops;
73672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
73772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
7385e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteLocked() {
7395e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
7405e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
7415e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
7425e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
7435e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
7445e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
7455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteNowLocked() {
7465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
7475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
7485e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
7495e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.removeCallbacks(mWriteRunner);
7505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.post(mWriteRunner);
7515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
7525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
75372e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
75472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        Ops ops = getOpsLocked(uid, packageName, edit);
75572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
75672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return null;
75772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
758f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        return getOpLocked(ops, code, edit);
759f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
760f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
761f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private Op getOpLocked(Ops ops, int code, boolean edit) {
762a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Op op = ops.get(code);
763a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (op == null) {
76435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
76535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
76635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
767e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op = new Op(ops.uid, ops.packageName, code);
768a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            ops.put(code, op);
769a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
7705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (edit) {
7715e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            scheduleWriteLocked();
77235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
773a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return op;
774a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
775a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
77635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readState() {
77735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
77835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (this) {
77935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                FileInputStream stream;
78035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
78135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    stream = mFile.openRead();
78235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (FileNotFoundException e) {
78335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
78435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    return;
78535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
78635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                boolean success = false;
78735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
78835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    XmlPullParser parser = Xml.newPullParser();
78935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    parser.setInput(stream, null);
79035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int type;
79135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.START_TAG
79235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && type != XmlPullParser.END_DOCUMENT) {
79335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        ;
79435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
79535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
79635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (type != XmlPullParser.START_TAG) {
79735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        throw new IllegalStateException("no start tag found");
79835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
79935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
80035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int outerDepth = parser.getDepth();
80135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
80235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
80335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
80435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            continue;
80535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
80635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
80735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        String tagName = parser.getName();
80835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (tagName.equals("pkg")) {
8090997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                            readPackage(parser);
81035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        } else {
81135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Slog.w(TAG, "Unknown element under <app-ops>: "
81235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    + parser.getName());
81335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            XmlUtils.skipCurrentTag(parser);
81435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
81535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
81635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    success = true;
81735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IllegalStateException e) {
81835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
81935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NullPointerException e) {
82035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NumberFormatException e) {
82235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (XmlPullParserException e) {
82435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IOException e) {
82635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IndexOutOfBoundsException e) {
82835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } finally {
83035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (!success) {
83135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mUidOps.clear();
83235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
83335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    try {
83435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        stream.close();
83535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } catch (IOException e) {
83635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
83735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
83835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
83935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
84035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
84135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
8420997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke    void readPackage(XmlPullParser parser) throws NumberFormatException,
84335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
84435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        String pkgName = parser.getAttributeValue(null, "n");
84535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
84635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
84735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
84835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
84935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
85035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
85135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
85235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
85335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
85435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("uid")) {
8550997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                readUid(parser, pkgName);
85635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
85735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
85835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
85935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
86035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
86135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
86235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
86335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
8640997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
86535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
86635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
86735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
86835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
86935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
87035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
87135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
87235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
87335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
87435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
87535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
87635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("op")) {
877e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n")));
8785e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String mode = parser.getAttributeValue(null, "m");
8795e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (mode != null) {
8800997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                    op.mode = Integer.parseInt(mode);
8815e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8825e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String time = parser.getAttributeValue(null, "t");
8835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
8845e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.time = Long.parseLong(time);
8855e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8865e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                time = parser.getAttributeValue(null, "r");
8875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
8885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.rejectTime = Long.parseLong(time);
8895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String dur = parser.getAttributeValue(null, "d");
8915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (dur != null) {
8925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.duration = Integer.parseInt(dur);
8935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
89435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.get(uid);
89535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (pkgOps == null) {
89635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps = new HashMap<String, Ops>();
89735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mUidOps.put(uid, pkgOps);
89835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
89935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Ops ops = pkgOps.get(pkgName);
90035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (ops == null) {
90135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ops = new Ops(pkgName, uid);
90235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps.put(pkgName, ops);
90335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
90435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                ops.put(op.op, op);
90535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
90635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
90735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
90835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
90935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
91035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
91135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
91235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
91335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void writeState() {
91435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
91535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
91635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
91735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            FileOutputStream stream;
91835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
91935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                stream = mFile.startWrite();
92035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
92135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state: " + e);
92235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return;
92335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
92435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
92535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
92635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlSerializer out = new FastXmlSerializer();
92735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.setOutput(stream, "utf-8");
92835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startDocument(null, true);
92935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startTag(null, "app-ops");
93035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
93135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (allOps != null) {
93235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    String lastPkg = null;
93335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    for (int i=0; i<allOps.size(); i++) {
93435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps pkg = allOps.get(i);
93535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (!pkg.getPackageName().equals(lastPkg)) {
93635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (lastPkg != null) {
93735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                out.endTag(null, "pkg");
93835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
93935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            lastPkg = pkg.getPackageName();
94035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "pkg");
94135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", lastPkg);
94235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
94335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.startTag(null, "uid");
94435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.attribute(null, "n", Integer.toString(pkg.getUid()));
94535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        List<AppOpsManager.OpEntry> ops = pkg.getOps();
94635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.size(); j++) {
94735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            AppOpsManager.OpEntry op = ops.get(j);
94835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "op");
94935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", Integer.toString(op.getOp()));
950f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                            if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
9515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "m", Integer.toString(op.getMode()));
9525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            long time = op.getTime();
9545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
9555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "t", Long.toString(time));
9565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            time = op.getRejectTime();
9585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
9595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "r", Long.toString(time));
9605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            int dur = op.getDuration();
9625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (dur != 0) {
9635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "d", Integer.toString(dur));
9645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
96535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.endTag(null, "op");
96635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
96735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "uid");
96835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
96935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (lastPkg != null) {
97035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "pkg");
97135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
97235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
97335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
97435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endTag(null, "app-ops");
97535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endDocument();
97635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.finishWrite(stream);
97735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
97835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state, restoring backup.", e);
97935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.failWrite(stream);
98035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
98135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
98235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
98335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
984a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
985a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
986a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
987a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
988a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Permission Denial: can't dump ApOps service from from pid="
989a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + Binder.getCallingPid()
990a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
991a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return;
992a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
993a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
994a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
995a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Current AppOps Service state:");
9965e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            final long now = System.currentTimeMillis();
997e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            boolean needSep = false;
998e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mOpModeWatchers.size() > 0) {
999e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1000e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Op mode watchers:");
1001e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mOpModeWatchers.size(); i++) {
1002e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
1003e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
1004e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i);
1005e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
1006e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
1007e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
1008e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1009e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1010e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1011e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mPackageModeWatchers.size() > 0) {
1012e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1013e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Package mode watchers:");
1014e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mPackageModeWatchers.size(); i++) {
1015e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
1016e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
1017e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i);
1018e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
1019e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
1020e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
1021e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1022e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1023e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1024e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mModeWatchers.size() > 0) {
1025e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1026e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  All mode watchers:");
1027e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mModeWatchers.size(); i++) {
1028e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mModeWatchers.keyAt(i));
1029e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print(" -> "); pw.println(mModeWatchers.valueAt(i));
1030e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1031e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1032e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mClients.size() > 0) {
1033e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1034e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Clients:");
1035e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mClients.size(); i++) {
1036e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mClients.keyAt(i)); pw.println(":");
1037e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ClientState cs = mClients.valueAt(i);
1038e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("      "); pw.println(cs);
1039e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) {
1040e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println("      Started ops:");
1041e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        for (int j=0; j<cs.mStartedOps.size(); j++) {
1042e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            Op op = cs.mStartedOps.get(j);
1043e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print("        "); pw.print("uid="); pw.print(op.uid);
1044e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" pkg="); pw.print(op.packageName);
1045e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
1046e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        }
1047e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1048e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1049e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1050e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (needSep) {
1051e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println();
1052e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1053a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
1054a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
1055a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
1056a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                for (Ops ops : pkgOps.values()) {
1057a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
1058a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    for (int j=0; j<ops.size(); j++) {
1059a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        Op op = ops.valueAt(j);
10605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
10615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print(": mode="); pw.print(op.mode);
10625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.time != 0) {
10635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
10645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
10655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
10665e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.rejectTime != 0) {
10675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
10685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
10695e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
1070a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        if (op.duration == -1) {
1071a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.println(" (running)");
1072a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        } else {
1073a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.print("; duration=");
1074a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    TimeUtils.formatDuration(op.duration, pw);
1075a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    pw.println();
1076a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        }
1077a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    }
1078a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
1079a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
1080a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
1081a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
1082a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn}
1083