1e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov/*
2e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * Copyright (C) 2015 The Android Open Source Project
3e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov *
4e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * Licensed under the Apache License, Version 2.0 (the "License");
5e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * you may not use this file except in compliance with the License.
6e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * You may obtain a copy of the License at
7e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov *
8e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov *      http://www.apache.org/licenses/LICENSE-2.0
9e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov *
10e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * Unless required by applicable law or agreed to in writing, software
11e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * distributed under the License is distributed on an "AS IS" BASIS,
12e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * See the License for the specific language governing permissions and
14e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * limitations under the License.
15e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov */
16e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
17e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovpackage android.support.v4.app;
18e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
19aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikasimport static android.os.Build.VERSION.SDK_INT;
20aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas
21aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikasimport android.app.AppOpsManager;
22e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovimport android.content.Context;
23e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovimport android.support.annotation.NonNull;
24e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
25e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov/**
26e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * Helper for accessing features in android.app.AppOpsManager
27e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * introduced after API level 4 in a backwards compatible fashion.
28e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov */
29c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final class AppOpsManagerCompat {
30e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
31e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
32e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller is allowed to
33e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * perform the given operation.
34e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
35e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_ALLOWED = 0;
36e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
37e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
38e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller is not allowed to perform
39e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * the given operation, and this attempt should <em>silently fail</em> (it
40e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * should not cause the app to crash).
41e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
42e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_IGNORED = 1;
43e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
44e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
45e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller should use its default
46e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * security check.  This mode is not normally used; it should only be used
47e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * with appop permissions, and callers must explicitly check for it and
48e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * deal with it.
49e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
50e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_DEFAULT = 3;
51e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
52c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes    private AppOpsManagerCompat() {}
53c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes
54e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
55e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Gets the app op name associated with a given permission.
56e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     *
57e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param permission The permission.
58e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return The app op associated with the permission or null.
59e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
60e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static String permissionToOp(@NonNull String permission) {
61aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        if (SDK_INT >= 23) {
62aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return AppOpsManager.permissionToOp(permission);
63aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        } else {
64aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return null;
65aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        }
66e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
67e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
68e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
69e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Make note of an application performing an operation.  Note that you must pass
70e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * in both the uid and name of the application to be checked; this function will verify
71e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
72e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * succeeds, the last execution time of the operation for this app will be updated to
73e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * the current time.
74e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param context Your context.
75e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
76e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param uid The user id of the application attempting to perform the operation.
77e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param packageName The name of the application attempting to perform the operation.
78e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
79e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
80e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * causing the app to crash).
81e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
82e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
83e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteOp(@NonNull Context context, @NonNull String op, int uid,
84e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String packageName) {
85aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        if (SDK_INT >= 23) {
86aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
87aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return appOpsManager.noteOp(op, uid, packageName);
88aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        } else {
89aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return MODE_IGNORED;
90aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        }
91e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
92e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
93e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    /**
94e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * Make note of an application performing an operation on behalf of another
95e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * application when handling an IPC. Note that you must pass the package name
96e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * of the application that is being proxied while its UID will be inferred from
97e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * the IPC state; this function will verify that the calling uid and proxied
98e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * package name match, and if not, return {@link #MODE_IGNORED}. If this call
99e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * succeeds, the last execution time of the operation for the proxied app and
100e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * your app will be updated to the current time.
101e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param context Your context.
102e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
103e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param proxiedPackageName The name of the application calling into the proxy application.
104e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
105e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
106e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * causing the app to crash).
107e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
108e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     */
109e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteProxyOp(@NonNull Context context, @NonNull String op,
110e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String proxiedPackageName) {
111aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        if (SDK_INT >= 23) {
112aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
113aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return appOpsManager.noteProxyOp(op, proxiedPackageName);
114aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        } else {
115aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas            return MODE_IGNORED;
116aa2232cbf2d14781533ffa664a472ffd35b4644fAurimas Liutikas        }
117e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    }
118e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov}
119