AppOpsService.java revision e799175b6ba3aadd972f4b861758d675d1f93987
1a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn/*
2a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Copyright (C) 2012 The Android Open Source Project
3a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn *
4a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * you may not use this file except in compliance with the License.
6a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * You may obtain a copy of the License at
7a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn *
8a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn *
10a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * See the License for the specific language governing permissions and
14a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn * limitations under the License.
15a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn */
16a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
17a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpackage com.android.server;
18a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.File;
20a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.FileDescriptor;
2135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileInputStream;
2235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileNotFoundException;
2335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.FileOutputStream;
2435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.io.IOException;
25a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.io.PrintWriter;
2635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.ArrayList;
27a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport java.util.HashMap;
2835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport java.util.List;
29a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
30a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
31a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.Context;
32a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager;
33a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
3435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.AsyncTask;
35a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Binder;
3635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.os.Handler;
37a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.Process;
38a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager;
39a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.UserHandle;
40a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.AtomicFile;
41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.Slog;
42a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.SparseArray;
43a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.util.TimeUtils;
4435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport android.util.Xml;
45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
4735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.FastXmlSerializer;
4835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport com.android.internal.util.XmlUtils;
4935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
5035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParser;
5135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
5235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackbornimport org.xmlpull.v1.XmlSerializer;
53a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
54a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornpublic class AppOpsService extends IAppOpsService.Stub {
55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    static final String TAG = "AppOps";
5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final boolean DEBUG = false;
5735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
5835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    // Write at most every 30 minutes.
5935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    static final long WRITE_DELAY = DEBUG ? 1000 : 30*60*1000;
60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
61a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    Context mContext;
62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final AtomicFile mFile;
6335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Handler mHandler;
6435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
6535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    boolean mWriteScheduled;
6635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    final Runnable mWriteRunner = new Runnable() {
6735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public void run() {
6835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (AppOpsService.this) {
6935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
7035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
7135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    @Override protected Void doInBackground(Void... params) {
7235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        writeState();
7335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        return null;
7435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
7535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                };
7635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
7735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
7835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
7935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    };
80a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
81a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final SparseArray<HashMap<String, Ops>> mUidOps
82a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            = new SparseArray<HashMap<String, Ops>>();
83a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final static class Ops extends SparseArray<Op> {
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final String packageName;
8635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public final int uid;
87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
8835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public Ops(String _packageName, int _uid) {
89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            packageName = _packageName;
9035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            uid = _uid;
91a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
92a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
94a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    final static class Op {
95a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public final int op;
96a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public int duration;
97a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public long time;
9835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        public int nesting;
99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
100a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        public Op(int _op) {
101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = _op;
102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
103a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
104a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
10535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public AppOpsService(File storagePath) {
10635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mFile = new AtomicFile(storagePath);
10735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mHandler = new Handler();
10835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        readState();
109a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
110a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
111a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void publish(Context context) {
112a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext = context;
113a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        ServiceManager.addService(Context.APP_OPS_SERVICE, asBinder());
114a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
115a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
116a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    public void shutdown() {
117a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Slog.w(TAG, "Writing app ops before shutdown...");
11835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        boolean doWrite = false;
11935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (this) {
12035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mWriteScheduled) {
12135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mWriteScheduled = false;
12235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                doWrite = true;
12335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
12435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
12535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (doWrite) {
12635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            writeState();
12735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
128a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
129a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
130a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
13135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
13235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
13335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
13435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        ArrayList<AppOpsManager.PackageOps> res = null;
135a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
13635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
13735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> packages = mUidOps.valueAt(i);
13835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                for (Ops pkgOps : packages.values()) {
13935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ArrayList<AppOpsManager.OpEntry> resOps = null;
14035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (ops == null) {
14135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        resOps = new ArrayList<AppOpsManager.OpEntry>();
14235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<pkgOps.size(); j++) {
14335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Op curOp = pkgOps.valueAt(j);
14435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
14535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    curOp.duration));
14635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
14735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } else {
14835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.length; j++) {
14935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Op curOp = pkgOps.get(ops[j]);
15035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (curOp != null) {
15135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                if (resOps == null) {
15235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    resOps = new ArrayList<AppOpsManager.OpEntry>();
15335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                }
15435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                resOps.add(new AppOpsManager.OpEntry(curOp.op, curOp.time,
15535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                        curOp.duration));
15635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
15735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
15835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
15935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (resOps != null) {
16035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (res == null) {
16135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            res = new ArrayList<AppOpsManager.PackageOps>();
16235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
16335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
16435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                pkgOps.packageName, pkgOps.uid, resOps);
16535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        res.add(resPackage);
16635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
16735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
168a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
169a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
17035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return res;
171a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
172a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
173a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
17435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int checkOperation(int code, int uid, String packageName) {
175a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        uid = handleIncomingUid(uid);
176a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
17735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, false);
178a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
17935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_ALLOWED;
180a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
181a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
182a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return AppOpsManager.MODE_ALLOWED;
183a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
184a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
185a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
18635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int noteOperation(int code, int uid, String packageName) {
187a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        uid = handleIncomingUid(uid);
188a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
18935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
190a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
19135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return AppOpsManager.MODE_IGNORED;
192a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
19335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.duration == -1) {
19435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Noting op not finished: uid " + uid + " pkg " + packageName
195a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration);
196a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
19735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.time = System.currentTimeMillis();
19835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.duration = 0;
199a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
20035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return AppOpsManager.MODE_ALLOWED;
201a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
202a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
203a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
20435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public int startOperation(int code, int uid, String packageName) {
205a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        uid = handleIncomingUid(uid);
206a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
20735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return AppOpsManager.MODE_IGNORED;
210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
21135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting == 0) {
21235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = System.currentTimeMillis();
21335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = -1;
214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
21535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            op.nesting++;
216a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
217a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return AppOpsManager.MODE_ALLOWED;
218a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
219a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
220a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
22135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    public void finishOperation(int code, int uid, String packageName) {
222a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        uid = handleIncomingUid(uid);
223a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
22435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Op op = getOpLocked(code, uid, packageName, true);
225a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (op == null) {
226a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
227a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
22835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (op.nesting <= 1) {
22935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (op.nesting == 1) {
23035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    op.duration = (int)(System.currentTimeMillis() - op.time);
23135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } else {
23235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Finishing op nesting under-run: uid " + uid + " pkg " + packageName
23335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + " code " + code + " time=" + op.time + " duration=" + op.duration
23435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + " nesting=" + op.nesting);
23535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
236e799175b6ba3aadd972f4b861758d675d1f93987Dianne Hackborn                op.nesting = 0;
23735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
23835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.nesting--;
239a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
240a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
241a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
242a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
243a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int handleIncomingUid(int uid) {
244a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (uid == Binder.getCallingUid()) {
245a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return uid;
246a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
248a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return uid;
249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
250a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
251a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
252a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return uid;
253a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
254a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
25535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
256a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        HashMap<String, Ops> pkgOps = mUidOps.get(uid);
257a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (pkgOps == null) {
25835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
25935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
26035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
261a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps = new HashMap<String, Ops>();
262a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mUidOps.put(uid, pkgOps);
263a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
264a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Ops ops = pkgOps.get(packageName);
265a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (ops == null) {
26635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
26735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
26835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
269a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // This is the first time we have seen this package name under this uid,
270a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            // so let's make sure it is valid.
271002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            final long ident = Binder.clearCallingIdentity();
272002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            try {
273002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                int pkgUid = -1;
274a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
275002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    pkgUid = mContext.getPackageManager().getPackageUid(packageName,
276002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                            UserHandle.getUserId(uid));
277002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                } catch (NameNotFoundException e) {
278a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
279002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                if (pkgUid != uid) {
280002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    // Oops!  The package name is not valid for the uid they are calling
281002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    // under.  Abort.
282002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    Slog.w(TAG, "Bad call: specified package " + packageName
283002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                            + " under uid " + uid + " but it is really " + pkgUid);
284002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                    return null;
285002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                }
286002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn            } finally {
287002a54e2291eeb3a3fd0b6b3f9dbc96a7c805062Dianne Hackborn                Binder.restoreCallingIdentity(ident);
288a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
28935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            ops = new Ops(packageName, uid);
290a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pkgOps.put(packageName, ops);
291a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
292a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        Op op = ops.get(code);
293a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (op == null) {
29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (!edit) {
29535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return null;
29635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
297a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            op = new Op(code);
298a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            ops.put(code, op);
299a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
30035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        if (edit && !mWriteScheduled) {
30135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            mWriteScheduled = true;
30235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            mHandler.postDelayed(mWriteRunner, WRITE_DELAY);
30335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
304a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        return op;
305a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
306a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
30735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readState() {
30835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
30935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            synchronized (this) {
31035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                FileInputStream stream;
31135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
31235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    stream = mFile.openRead();
31335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (FileNotFoundException e) {
31435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.i(TAG, "No existing app ops " + mFile.getBaseFile() + "; starting empty");
31535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    return;
31635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
31735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                boolean success = false;
31835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                try {
31935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    XmlPullParser parser = Xml.newPullParser();
32035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    parser.setInput(stream, null);
32135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int type;
32235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.START_TAG
32335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && type != XmlPullParser.END_DOCUMENT) {
32435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        ;
32535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
32635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
32735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (type != XmlPullParser.START_TAG) {
32835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        throw new IllegalStateException("no start tag found");
32935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
33035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
33135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    int outerDepth = parser.getDepth();
33235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
33335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
33435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
33535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            continue;
33635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
33735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
33835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        String tagName = parser.getName();
33935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (tagName.equals("pkg")) {
34035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            readPackage(parser);
34135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        } else {
34235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Slog.w(TAG, "Unknown element under <app-ops>: "
34335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                    + parser.getName());
34435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            XmlUtils.skipCurrentTag(parser);
34535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
34635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
34735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    success = true;
34835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IllegalStateException e) {
34935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
35035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NullPointerException e) {
35135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
35235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (NumberFormatException e) {
35335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
35435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (XmlPullParserException e) {
35535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
35635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IOException e) {
35735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
35835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } catch (IndexOutOfBoundsException e) {
35935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Slog.w(TAG, "Failed parsing " + e);
36035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                } finally {
36135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (!success) {
36235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mUidOps.clear();
36335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
36435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    try {
36535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        stream.close();
36635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    } catch (IOException e) {
36735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
36835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
36935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
37035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
37135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
37235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
37335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readPackage(XmlPullParser parser) throws NumberFormatException,
37435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
37535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        String pkgName = parser.getAttributeValue(null, "n");
37635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
37735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
37835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
37935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
38035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
38135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
38235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
38335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
38435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
38535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("uid")) {
38635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                readUid(parser, pkgName);
38735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
38835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
38935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
39035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
39135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
39235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
39335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
39435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
39535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void readUid(XmlPullParser parser, String pkgName) throws NumberFormatException,
39635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            XmlPullParserException, IOException {
39735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int uid = Integer.parseInt(parser.getAttributeValue(null, "n"));
39835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int outerDepth = parser.getDepth();
39935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        int type;
40035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
40135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
40235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
40335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                continue;
40435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
40535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
40635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            String tagName = parser.getName();
40735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (tagName.equals("op")) {
40835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Op op = new Op(Integer.parseInt(parser.getAttributeValue(null, "n")));
40935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.time = Long.parseLong(parser.getAttributeValue(null, "t"));
41035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                op.duration = Integer.parseInt(parser.getAttributeValue(null, "d"));
41135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.get(uid);
41235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (pkgOps == null) {
41335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps = new HashMap<String, Ops>();
41435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mUidOps.put(uid, pkgOps);
41535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
41635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Ops ops = pkgOps.get(pkgName);
41735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (ops == null) {
41835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    ops = new Ops(pkgName, uid);
41935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    pkgOps.put(pkgName, ops);
42035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
42135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                ops.put(op.op, op);
42235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } else {
42335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Unknown element under <pkg>: "
42435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        + parser.getName());
42535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlUtils.skipCurrentTag(parser);
42635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
42735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
42835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
42935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
43035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    void writeState() {
43135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        synchronized (mFile) {
43235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            List<AppOpsManager.PackageOps> allOps = getPackagesForOps(null);
43335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
43435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            FileOutputStream stream;
43535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
43635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                stream = mFile.startWrite();
43735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
43835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state: " + e);
43935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                return;
44035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
44135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
44235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            try {
44335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                XmlSerializer out = new FastXmlSerializer();
44435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.setOutput(stream, "utf-8");
44535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startDocument(null, true);
44635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.startTag(null, "app-ops");
44735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
44835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                if (allOps != null) {
44935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    String lastPkg = null;
45035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    for (int i=0; i<allOps.size(); i++) {
45135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        AppOpsManager.PackageOps pkg = allOps.get(i);
45235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        if (!pkg.getPackageName().equals(lastPkg)) {
45335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            if (lastPkg != null) {
45435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                                out.endTag(null, "pkg");
45535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            }
45635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            lastPkg = pkg.getPackageName();
45735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "pkg");
45835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", lastPkg);
45935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
46035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.startTag(null, "uid");
46135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.attribute(null, "n", Integer.toString(pkg.getUid()));
46235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        List<AppOpsManager.OpEntry> ops = pkg.getOps();
46335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        for (int j=0; j<ops.size(); j++) {
46435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            AppOpsManager.OpEntry op = ops.get(j);
46535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.startTag(null, "op");
46635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "n", Integer.toString(op.getOp()));
46735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "t", Long.toString(op.getTime()));
46835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.attribute(null, "d", Integer.toString(op.getDuration()));
46935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            out.endTag(null, "op");
47035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        }
47135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "uid");
47235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
47335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    if (lastPkg != null) {
47435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        out.endTag(null, "pkg");
47535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    }
47635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                }
47735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
47835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endTag(null, "app-ops");
47935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                out.endDocument();
48035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.finishWrite(stream);
48135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            } catch (IOException e) {
48235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                Slog.w(TAG, "Failed to write state, restoring backup.", e);
48335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                mFile.failWrite(stream);
48435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            }
48535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        }
48635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    }
48735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn
488a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    @Override
489a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
490a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
491a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                != PackageManager.PERMISSION_GRANTED) {
492a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Permission Denial: can't dump ApOps service from from pid="
493a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + Binder.getCallingPid()
494a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    + ", uid=" + Binder.getCallingUid());
495a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            return;
496a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
497a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
498a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        synchronized (this) {
499a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            pw.println("Current AppOps Service state:");
500a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            for (int i=0; i<mUidOps.size(); i++) {
501a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                pw.print("  Uid "); UserHandle.formatUid(pw, mUidOps.keyAt(i)); pw.println(":");
502a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                HashMap<String, Ops> pkgOps = mUidOps.valueAt(i);
503a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                for (Ops ops : pkgOps.values()) {
504a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    pw.print("    Package "); pw.print(ops.packageName); pw.println(":");
505a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    for (int j=0; j<ops.size(); j++) {
506a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        Op op = ops.valueAt(j);
507a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        pw.print("      "); pw.print(AppOpsManager.opToString(op.op));
508a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        pw.print(": time=");
509a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        TimeUtils.formatDuration(System.currentTimeMillis()-op.time, pw);
510a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        pw.print(" ago");
511a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        if (op.duration == -1) {
512a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.println(" (running)");
513a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        } else {
514a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                            pw.print("; duration=");
515a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    TimeUtils.formatDuration(op.duration, pw);
516a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                                    pw.println();
517a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                        }
518a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    }
519a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
520a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
521a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
522a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
523a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn}
524