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);
4388828d3a153e28fe631edcd5145e6cc706e0b34c8Dianne Hackborn                        if (AppOpsManager.opAllowsReset(curOp.op)
4398828d3a153e28fe631edcd5145e6cc706e0b34c8Dianne Hackborn                                && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
440f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                            curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
441607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            changed = true;
442607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
443607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                                    mOpModeWatchers.get(curOp.op));
444607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                            callbacks = addCallbacks(callbacks, packageName, curOp.op,
445607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                                    mPackageModeWatchers.get(packageName));
4467f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                            if (curOp.time == 0 && curOp.rejectTime == 0) {
4477f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                                pkgOps.removeAt(j);
4487f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                            }
449607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        }
450607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    }
4517f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    if (pkgOps.size() == 0) {
4527f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                        it.remove();
4537f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    }
4547f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                }
4557f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                if (packages.size() == 0) {
4567f09ec39b6fd7f24751f814649f12ea686cb28d4Dianne Hackborn                    mUidOps.removeAt(i);
457607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                }
458607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
459607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            if (changed) {
460607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                scheduleWriteNowLocked();
461607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
462607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
463607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        if (callbacks != null) {
464607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            for (Map.Entry<Callback, ArrayList<Pair<String, Integer>>> ent : callbacks.entrySet()) {
465607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                Callback cb = ent.getKey();
466607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                ArrayList<Pair<String, Integer>> reports = ent.getValue();
467607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                for (int i=0; i<reports.size(); i++) {
468607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    Pair<String, Integer> rep = reports.get(i);
469607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    try {
470607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                        cb.mCallback.opChanged(rep.second, rep.first);
471607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    } catch (RemoteException e) {
472607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                    }
473607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn                }
474607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn            }
475607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn        }
476607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn    }
477607b414d0444067e166fa54d8ea37563f2715ea3Dianne Hackborn
478c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
479c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void startWatchingMode(int op, String packageName, IAppOpsCallback callback) {
480c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
481c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            op = AppOpsManager.opToSwitch(op);
482c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.get(callback.asBinder());
483c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb == null) {
484c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb = new Callback(callback);
485c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                mModeWatchers.put(callback.asBinder(), cb);
486c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
487c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (op != AppOpsManager.OP_NONE) {
488c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mOpModeWatchers.get(op);
489c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
490c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
491c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mOpModeWatchers.put(op, cbs);
492c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
493c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
494c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
495c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (packageName != null) {
496c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                ArrayList<Callback> cbs = mPackageModeWatchers.get(packageName);
497c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                if (cbs == null) {
498c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs = new ArrayList<Callback>();
499c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    mPackageModeWatchers.put(packageName, cbs);
500c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
501c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cbs.add(cb);
502c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
503c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
504c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    }
505c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn
506c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    @Override
507c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn    public void stopWatchingMode(IAppOpsCallback callback) {
508c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        synchronized (this) {
509c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            Callback cb = mModeWatchers.remove(callback.asBinder());
510c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            if (cb != null) {
511c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                cb.unlinkToDeath();
512e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mOpModeWatchers.size()-1; i>=0; i--) {
513c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    ArrayList<Callback> cbs = mOpModeWatchers.valueAt(i);
514c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    cbs.remove(cb);
515c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    if (cbs.size() <= 0) {
516c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                        mOpModeWatchers.removeAt(i);
517c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
518c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
519e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=mPackageModeWatchers.size()-1; i>=0; i--) {
520e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> cbs = mPackageModeWatchers.valueAt(i);
521e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    cbs.remove(cb);
522e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cbs.size() <= 0) {
523e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        mPackageModeWatchers.removeAt(i);
524c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                    }
525c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn                }
526c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn            }
527c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        }
5285e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
5295e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
5305e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    @Override
531e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public IBinder getToken(IBinder clientToken) {
532e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        synchronized (this) {
533e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            ClientState cs = mClients.get(clientToken);
534e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (cs == null) {
535e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                cs = new ClientState(clientToken);
536e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mClients.put(clientToken, cs);
537e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
538e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            return cs;
539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
540e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
541e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
542e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    @Override
54335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int checkOperation(int code, int uid, String packageName) {
544f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
545961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
546a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
547f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(AppOpsManager.opToSwitch(code), uid, packageName, false);
548a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
549f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                return AppOpsManager.opToDefaultMode(code);
550a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
5515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return op.mode;
552a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
553a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
554a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
555a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
556911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    public int checkPackage(int uid, String packageName) {
557911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey        synchronized (this) {
558911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            if (getOpsLocked(uid, packageName, true) != null) {
559911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ALLOWED;
560911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            } else {
561911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
562911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey            }
563911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey        }
564911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    }
565911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey
566911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey    @Override
56735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int noteOperation(int code, int uid, String packageName) {
568f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
569961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
570a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
571f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
572f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
5735e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
5745e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
575911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
576a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
577f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
57835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.duration == -1) {
57935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
580a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
581a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
58235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.duration = 0;
583f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
584f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
585f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
586f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
587f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
5885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
589f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
5905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
5915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "noteOperation: allowing code " + code + " uid " + uid
5925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
5935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            op.time = System.currentTimeMillis();
594514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            op.rejectTime = 0;
5955e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
596a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
597a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
598a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
599a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
600e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public int startOperation(IBinder token, int code, int uid, String packageName) {
601f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
602961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
603e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
604a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
605f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Ops ops = getOpsLocked(uid, packageName, true);
606f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (ops == null) {
6075e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
6085e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        + " package " + packageName);
609911d7f411f36f2279aae44c89ff1d33a29140046Jeff Sharkey                return AppOpsManager.MODE_ERRORED;
610a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
611f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            Op op = getOpLocked(ops, code, true);
612f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final int switchCode = AppOpsManager.opToSwitch(code);
613f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
614f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
615f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
616f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                        + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
6175e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                op.rejectTime = System.currentTimeMillis();
618f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                return switchOp.mode;
6195e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            }
6205e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
6215e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    + " package " + packageName);
62235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting == 0) {
62335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = System.currentTimeMillis();
624514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                op.rejectTime = 0;
62535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = -1;
626a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
62735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.nesting++;
628e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
629e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                client.mStartedOps.add(op);
630e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
6315e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            return AppOpsManager.MODE_ALLOWED;
632a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
633a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
634a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
635a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
636e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    public void finishOperation(IBinder token, int code, int uid, String packageName) {
637f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
638961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        verifyIncomingOp(code);
639e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        ClientState client = (ClientState)token;
640a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
64135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
642a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
643a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
644a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
645e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (client.mStartedOps != null) {
646e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                if (!client.mStartedOps.remove(op)) {
647e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    throw new IllegalStateException("Operation not started: uid" + op.uid
648e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            + " pkg=" + op.packageName + " op=" + op.op);
64935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
650e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
651e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            finishOperationLocked(op);
652e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        }
653e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    }
654e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn
655e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn    void finishOperationLocked(Op op) {
656e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        if (op.nesting <= 1) {
657e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (op.nesting == 1) {
658e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.duration = (int)(System.currentTimeMillis() - op.time);
659e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                op.time += op.duration;
66035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
661e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Slog.w(TAG, "Finishing op nesting under-run: uid " + op.uid + " pkg "
662e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + op.packageName + " code " + op.op + " time=" + op.time
663e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        + " duration=" + op.duration + " nesting=" + op.nesting);
664a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
665e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting = 0;
666e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn        } else {
667e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op.nesting--;
668a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
669a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
670a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
671f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
672a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (uid == Binder.getCallingUid()) {
673f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
674a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
675a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
676f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
677a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
678a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
679a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
680a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
681a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
682961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    private void verifyIncomingOp(int op) {
683961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        if (op >= 0 && op < AppOpsManager._NUM_OP) {
684961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn            return;
685961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        }
686961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn        throw new IllegalArgumentException("Bad operation #" + op);
687961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn    }
688961321fe4ed4431a6362d729d9e4ea26bdecde61Dianne Hackborn
68972e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Ops getOpsLocked(int uid, String packageName, boolean edit) {
690a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        HashMap<String, Ops> pkgOps = mUidOps.get(uid);
691a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (pkgOps == null) {
69235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
69335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
69435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
695a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps = new HashMap<String, Ops>();
696a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mUidOps.put(uid, pkgOps);
697a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
698514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        if (uid == 0) {
699514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "root";
700514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        } else if (uid == Process.SHELL_UID) {
701514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            packageName = "com.android.shell";
702514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn        }
703a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Ops ops = pkgOps.get(packageName);
704a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (ops == null) {
70535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
70635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
70735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
708a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // This is the first time we have seen this package name under this uid,
709a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // so let's make sure it is valid.
710514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn            if (uid != 0) {
711514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                final long ident = Binder.clearCallingIdentity();
712a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
713514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    int pkgUid = -1;
714514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    try {
715514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        pkgUid = mContext.getPackageManager().getPackageUid(packageName,
716514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                UserHandle.getUserId(uid));
717514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    } catch (NameNotFoundException e) {
718713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        if ("media".equals(packageName)) {
719713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                            pkgUid = Process.MEDIA_UID;
720713df150b92a0a5eea877f99405e31eefbf93a09Dianne Hackborn                        }
721514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
722514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    if (pkgUid != uid) {
723514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // Oops!  The package name is not valid for the uid they are calling
724514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        // under.  Abort.
725514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        Slog.w(TAG, "Bad call: specified package " + packageName
726514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                                + " under uid " + uid + " but it is really " + pkgUid);
727514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                        return null;
728514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    }
729514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                } finally {
730514074fae81028937eda29e782c92e8ea78d85d2Dianne Hackborn                    Binder.restoreCallingIdentity(ident);
731002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                }
732a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
73335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            ops = new Ops(packageName, uid);
734a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps.put(packageName, ops);
735a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
73672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        return ops;
73772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    }
73872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn
7395e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteLocked() {
7405e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
7415e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
7425e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
7435e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
7445e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
7455e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
7465e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    private void scheduleWriteNowLocked() {
7475e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (!mWriteScheduled) {
7485e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            mWriteScheduled = true;
7495e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        }
7505e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.removeCallbacks(mWriteRunner);
7515e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        mHandler.post(mWriteRunner);
7525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn    }
7535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn
75472e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
75572e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        Ops ops = getOpsLocked(uid, packageName, edit);
75672e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        if (ops == null) {
75772e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn            return null;
75872e3983d38f656cfa8c7a038eb80bdd9ea06768eDianne Hackborn        }
759f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        return getOpLocked(ops, code, edit);
760f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
761f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
762f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private Op getOpLocked(Ops ops, int code, boolean edit) {
763a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Op op = ops.get(code);
764a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (op == null) {
76535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
76635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
76735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
768e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            op = new Op(ops.uid, ops.packageName, code);
769a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            ops.put(code, op);
770a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
7715e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn        if (edit) {
7725e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            scheduleWriteLocked();
77335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
774a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return op;
775a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
776a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
77735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readState() {
77835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
77935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (this) {
78035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                FileInputStream stream;
78135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
78235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    stream = mFile.openRead();
78335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (FileNotFoundException e) {
78435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
78535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    return;
78635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
78735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                boolean success = false;
78835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
78935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    XmlPullParser parser = Xml.newPullParser();
79035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    parser.setInput(stream, null);
79135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int type;
79235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.START_TAG
79335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && type != XmlPullParser.END_DOCUMENT) {
79435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        ;
79535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
79635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
79735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (type != XmlPullParser.START_TAG) {
79835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        throw new IllegalStateException("no start tag found");
79935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
80035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
80135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int outerDepth = parser.getDepth();
80235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
80335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
80435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
80535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            continue;
80635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
80735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
80835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        String tagName = parser.getName();
80935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (tagName.equals("pkg")) {
8100997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                            readPackage(parser);
81135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        } else {
81235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Slog.w(TAG, "Unknown element under <app-ops>: "
81335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    + parser.getName());
81435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            XmlUtils.skipCurrentTag(parser);
81535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
81635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
81735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    success = true;
81835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IllegalStateException e) {
81935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NullPointerException e) {
82135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NumberFormatException e) {
82335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (XmlPullParserException e) {
82535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IOException e) {
82735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
82835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IndexOutOfBoundsException e) {
82935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
83035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } finally {
83135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (!success) {
83235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mUidOps.clear();
83335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
83435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    try {
83535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        stream.close();
83635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } catch (IOException e) {
83735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
83835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
83935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
84035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
84135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
84235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
8430997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke    void readPackage(XmlPullParser parser) throws NumberFormatException,
84435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
84535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        String pkgName = parser.getAttributeValue(null, "n");
84635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
84735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
84835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
84935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
85035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
85135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
85235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
85335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
85435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
85535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("uid")) {
8560997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                readUid(parser, pkgName);
85735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
85835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
85935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
86035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
86135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
86235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
86335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
86435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
8650997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
86635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
86735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
86835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
86935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
87035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
87135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
87235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
87335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
87435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
87535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
87635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
87735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("op")) {
878e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                Op op = new Op(uid, pkgName, Integer.parseInt(parser.getAttributeValue(null, "n")));
8795e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String mode = parser.getAttributeValue(null, "m");
8805e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (mode != null) {
8810997c5bd79d11e6ecb11970bfd9b9b911001ac0aDave Burke                    op.mode = Integer.parseInt(mode);
8825e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8835e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String time = parser.getAttributeValue(null, "t");
8845e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
8855e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.time = Long.parseLong(time);
8865e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8875e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                time = parser.getAttributeValue(null, "r");
8885e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (time != null) {
8895e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.rejectTime = Long.parseLong(time);
8905e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
8915e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                String dur = parser.getAttributeValue(null, "d");
8925e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                if (dur != null) {
8935e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                    op.duration = Integer.parseInt(dur);
8945e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                }
89535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.get(uid);
89635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (pkgOps == null) {
89735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps = new HashMap<String, Ops>();
89835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mUidOps.put(uid, pkgOps);
89935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
90035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Ops ops = pkgOps.get(pkgName);
90135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (ops == null) {
90235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ops = new Ops(pkgName, uid);
90335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps.put(pkgName, ops);
90435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
90535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                ops.put(op.op, op);
90635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
90735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
90835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
90935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
91035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
91135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
91235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
91335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
91435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void writeState() {
91535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
91635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
91735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
91835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            FileOutputStream stream;
91935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
92035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                stream = mFile.startWrite();
92135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
92235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state: " + e);
92335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return;
92435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
92535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
92635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
92735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlSerializer out = new FastXmlSerializer();
92835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.setOutput(stream, "utf-8");
92935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startDocument(null, true);
93035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startTag(null, "app-ops");
93135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
93235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (allOps != null) {
93335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    String lastPkg = null;
93435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    for (int i=0; i<allOps.size(); i++) {
93535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps pkg = allOps.get(i);
93635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (!pkg.getPackageName().equals(lastPkg)) {
93735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (lastPkg != null) {
93835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                out.endTag(null, "pkg");
93935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
94035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            lastPkg = pkg.getPackageName();
94135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "pkg");
94235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", lastPkg);
94335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
94435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.startTag(null, "uid");
94535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.attribute(null, "n", Integer.toString(pkg.getUid()));
94635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        List<AppOpsManager.OpEntry> ops = pkg.getOps();
94735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.size(); j++) {
94835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            AppOpsManager.OpEntry op = ops.get(j);
94935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "op");
95035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", Integer.toString(op.getOp()));
951f5d831915dd11e77cdcf5669228c55fe17a21c5eDavid Braun                            if (op.getMode() != AppOpsManager.opToDefaultMode(op.getOp())) {
9525e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "m", Integer.toString(op.getMode()));
9535e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9545e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            long time = op.getTime();
9555e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
9565e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "t", Long.toString(time));
9575e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9585e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            time = op.getRejectTime();
9595e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (time != 0) {
9605e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "r", Long.toString(time));
9615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
9625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            int dur = op.getDuration();
9635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            if (dur != 0) {
9645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                                out.attribute(null, "d", Integer.toString(dur));
9655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            }
96635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.endTag(null, "op");
96735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
96835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "uid");
96935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
97035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (lastPkg != null) {
97135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "pkg");
97235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
97335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
97435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
97535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endTag(null, "app-ops");
97635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endDocument();
97735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.finishWrite(stream);
97835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
97935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state, restoring backup.", e);
98035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.failWrite(stream);
98135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
98235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
98335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
98435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
985a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
986a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
987a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
988a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
989a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Permission Denial: can't dump ApOps service from from pid="
990a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + Binder.getCallingPid()
991a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
992a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return;
993a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
994a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
995a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
996a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Current AppOps Service state:");
9975e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn            final long now = System.currentTimeMillis();
998e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            boolean needSep = false;
999e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mOpModeWatchers.size() > 0) {
1000e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1001e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Op mode watchers:");
1002e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mOpModeWatchers.size(); i++) {
1003e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Op "); pw.print(AppOpsManager.opToName(mOpModeWatchers.keyAt(i)));
1004e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
1005e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mOpModeWatchers.valueAt(i);
1006e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
1007e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
1008e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
1009e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1010e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1011e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1012e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mPackageModeWatchers.size() > 0) {
1013e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1014e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Package mode watchers:");
1015e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mPackageModeWatchers.size(); i++) {
1016e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    Pkg "); pw.print(mPackageModeWatchers.keyAt(i));
1017e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.println(":");
1018e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ArrayList<Callback> callbacks = mPackageModeWatchers.valueAt(i);
1019e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    for (int j=0; j<callbacks.size(); j++) {
1020e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.print("      #"); pw.print(j); pw.print(": ");
1021e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println(callbacks.get(j));
1022e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1023e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1024e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1025e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mModeWatchers.size() > 0) {
1026e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1027e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  All mode watchers:");
1028e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mModeWatchers.size(); i++) {
1029e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mModeWatchers.keyAt(i));
1030e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print(" -> "); pw.println(mModeWatchers.valueAt(i));
1031e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1032e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1033e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (mClients.size() > 0) {
1034e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                needSep = true;
1035e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println("  Clients:");
1036e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                for (int i=0; i<mClients.size(); i++) {
1037e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("    "); pw.print(mClients.keyAt(i)); pw.println(":");
1038e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    ClientState cs = mClients.valueAt(i);
1039e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    pw.print("      "); pw.println(cs);
1040e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    if (cs.mStartedOps != null && cs.mStartedOps.size() > 0) {
1041e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        pw.println("      Started ops:");
1042e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        for (int j=0; j<cs.mStartedOps.size(); j++) {
1043e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            Op op = cs.mStartedOps.get(j);
1044e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print("        "); pw.print("uid="); pw.print(op.uid);
1045e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" pkg="); pw.print(op.packageName);
1046e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                            pw.print(" op="); pw.println(AppOpsManager.opToName(op.op));
1047e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        }
1048e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                    }
1049e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                }
1050e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1051e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            if (needSep) {
1052e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                pw.println();
1053e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn            }
1054a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
1055a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
1056a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
1057a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                for (Ops ops : pkgOps.values()) {
1058a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
1059a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    for (int j=0; j<ops.size(); j++) {
1060a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        Op op = ops.valueAt(j);
10615e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print("      "); pw.print(AppOpsManager.opToName(op.op));
10625e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        pw.print(": mode="); pw.print(op.mode);
10635e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.time != 0) {
10645e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; time="); TimeUtils.formatDuration(now-op.time, pw);
10655e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
10665e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
10675e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        if (op.rejectTime != 0) {
10685e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print("; rejectTime="); TimeUtils.formatDuration(now-op.rejectTime, pw);
10695e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                            pw.print(" ago");
10705e45ee6752528791deb66b83d76250685de15d47Dianne Hackborn                        }
1071a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        if (op.duration == -1) {
1072a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.println(" (running)");
1073a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        } else {
1074a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.print("; duration=");
1075a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    TimeUtils.formatDuration(op.duration, pw);
1076a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    pw.println();
1077a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        }
1078a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    }
1079a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
1080a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
1081a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
1082a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
1083a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn}
1084