AppOpsManager.java revision d8e1dbb6bc1fbaf4f2e38c3ba92ced94270deaac
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
19import com.android.internal.app.IAppOpsService;
20
21import java.util.ArrayList;
22import java.util.List;
23
24import android.content.Context;
25import android.os.Parcel;
26import android.os.Parcelable;
27import android.os.Process;
28import android.os.RemoteException;
29
30/** @hide */
31public class AppOpsManager {
32    final Context mContext;
33    final IAppOpsService mService;
34
35    public static final int MODE_ALLOWED = 0;
36    public static final int MODE_IGNORED = 1;
37    public static final int MODE_ERRORED = 2;
38
39    public static final int OP_COARSE_LOCATION = 0;
40    public static final int OP_FINE_LOCATION = 1;
41    public static final int OP_GPS = 2;
42    public static final int OP_VIBRATE = 3;
43    public static final int OP_READ_CONTACTS = 4;
44    public static final int OP_WRITE_CONTACTS = 5;
45    public static final int OP_READ_CALL_LOG = 6;
46    public static final int OP_WRITE_CALL_LOG = 7;
47
48    public static String opToString(int op) {
49        switch (op) {
50            case OP_COARSE_LOCATION: return "COARSE_LOCATION";
51            case OP_FINE_LOCATION: return "FINE_LOCATION";
52            case OP_GPS: return "GPS";
53            case OP_VIBRATE: return "VIBRATE";
54            case OP_READ_CONTACTS: return "READ_CONTACTS";
55            case OP_WRITE_CONTACTS: return "WRITE_CONTACTS";
56            case OP_READ_CALL_LOG: return "READ_CALL_LOG";
57            case OP_WRITE_CALL_LOG: return "WRITE_CALL_LOG";
58            default: return "Unknown(" + op + ")";
59        }
60    }
61
62    public static class PackageOps implements Parcelable {
63        private final String mPackageName;
64        private final int mUid;
65        private final List<OpEntry> mEntries;
66
67        public PackageOps(String packageName, int uid, List<OpEntry> entries) {
68            mPackageName = packageName;
69            mUid = uid;
70            mEntries = entries;
71        }
72
73        public String getPackageName() {
74            return mPackageName;
75        }
76
77        public int getUid() {
78            return mUid;
79        }
80
81        public List<OpEntry> getOps() {
82            return mEntries;
83        }
84
85        @Override
86        public int describeContents() {
87            return 0;
88        }
89
90        @Override
91        public void writeToParcel(Parcel dest, int flags) {
92            dest.writeString(mPackageName);
93            dest.writeInt(mUid);
94            dest.writeInt(mEntries.size());
95            for (int i=0; i<mEntries.size(); i++) {
96                mEntries.get(i).writeToParcel(dest, flags);
97            }
98        }
99
100        PackageOps(Parcel source) {
101            mPackageName = source.readString();
102            mUid = source.readInt();
103            mEntries = new ArrayList<OpEntry>();
104            final int N = source.readInt();
105            for (int i=0; i<N; i++) {
106                mEntries.add(OpEntry.CREATOR.createFromParcel(source));
107            }
108        }
109
110        public static final Creator<PackageOps> CREATOR = new Creator<PackageOps>() {
111            @Override public PackageOps createFromParcel(Parcel source) {
112                return new PackageOps(source);
113            }
114
115            @Override public PackageOps[] newArray(int size) {
116                return new PackageOps[size];
117            }
118        };
119    }
120
121    public static class OpEntry implements Parcelable {
122        private final int mOp;
123        private final long mTime;
124        private final int mDuration;
125
126        public OpEntry(int op, long time, int duration) {
127            mOp = op;
128            mTime = time;
129            mDuration = duration;
130        }
131
132        public int getOp() {
133            return mOp;
134        }
135
136        public long getTime() {
137            return mTime;
138        }
139
140        public boolean isRunning() {
141            return mDuration == -1;
142        }
143
144        public int getDuration() {
145            return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration;
146        }
147
148        @Override
149        public int describeContents() {
150            return 0;
151        }
152
153        @Override
154        public void writeToParcel(Parcel dest, int flags) {
155            dest.writeInt(mOp);
156            dest.writeLong(mTime);
157            dest.writeInt(mDuration);
158        }
159
160        OpEntry(Parcel source) {
161            mOp = source.readInt();
162            mTime = source.readLong();
163            mDuration = source.readInt();
164        }
165
166        public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() {
167            @Override public OpEntry createFromParcel(Parcel source) {
168                return new OpEntry(source);
169            }
170
171            @Override public OpEntry[] newArray(int size) {
172                return new OpEntry[size];
173            }
174        };
175    }
176
177    public AppOpsManager(Context context, IAppOpsService service) {
178        mContext = context;
179        mService = service;
180    }
181
182    public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
183        try {
184            return mService.getPackagesForOps(ops);
185        } catch (RemoteException e) {
186        }
187        return null;
188    }
189
190    public int checkOp(int op, int uid, String packageName) {
191        try {
192            int mode = mService.checkOperation(op, uid, packageName);
193            if (mode == MODE_ERRORED) {
194                throw new SecurityException("Operation not allowed");
195            }
196            return mode;
197        } catch (RemoteException e) {
198        }
199        return MODE_IGNORED;
200    }
201
202    public int checkOpNoThrow(int op, int uid, String packageName) {
203        try {
204            return mService.checkOperation(op, uid, packageName);
205        } catch (RemoteException e) {
206        }
207        return MODE_IGNORED;
208    }
209
210    public int noteOp(int op, int uid, String packageName) {
211        try {
212            int mode = mService.noteOperation(op, uid, packageName);
213            if (mode == MODE_ERRORED) {
214                throw new SecurityException("Operation not allowed");
215            }
216            return mode;
217        } catch (RemoteException e) {
218        }
219        return MODE_IGNORED;
220    }
221
222    public int noteOpNoThrow(int op, int uid, String packageName) {
223        try {
224            return mService.noteOperation(op, uid, packageName);
225        } catch (RemoteException e) {
226        }
227        return MODE_IGNORED;
228    }
229
230    public int noteOp(int op) {
231        return noteOp(op, Process.myUid(), mContext.getBasePackageName());
232    }
233
234    public int startOp(int op, int uid, String packageName) {
235        try {
236            int mode = mService.startOperation(op, uid, packageName);
237            if (mode == MODE_ERRORED) {
238                throw new SecurityException("Operation not allowed");
239            }
240            return mode;
241        } catch (RemoteException e) {
242        }
243        return MODE_IGNORED;
244    }
245
246    public int startOpNoThrow(int op, int uid, String packageName) {
247        try {
248            return mService.startOperation(op, uid, packageName);
249        } catch (RemoteException e) {
250        }
251        return MODE_IGNORED;
252    }
253
254    public int startOp(int op) {
255        return startOp(op, Process.myUid(), mContext.getBasePackageName());
256    }
257
258    public void finishOp(int op, int uid, String packageName) {
259        try {
260            mService.finishOperation(op, uid, packageName);
261        } catch (RemoteException e) {
262        }
263    }
264
265    public void finishOp(int op) {
266        finishOp(op, Process.myUid(), mContext.getBasePackageName());
267    }
268}
269