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
19e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovimport android.content.Context;
20e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovimport android.os.Build;
21e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovimport android.support.annotation.NonNull;
22e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
23e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov/**
24e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * Helper for accessing features in android.app.AppOpsManager
25e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov * introduced after API level 4 in a backwards compatible fashion.
26e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov */
27e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganovpublic class AppOpsManagerCompat {
28e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
29e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
30e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller is allowed to
31e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * perform the given operation.
32e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
33e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_ALLOWED = 0;
34e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
35e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
36e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller is not allowed to perform
37e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * the given operation, and this attempt should <em>silently fail</em> (it
38e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * should not cause the app to crash).
39e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
40e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_IGNORED = 1;
41e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
42e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
43e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Result from {@link #noteOp}: the given caller should use its default
44e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * security check.  This mode is not normally used; it should only be used
45e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * with appop permissions, and callers must explicitly check for it and
46e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * deal with it.
47e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
48e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static final int MODE_DEFAULT = 3;
49e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
50e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    private static class AppOpsManagerImpl {
51e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public String permissionToOp(String permission) {
52e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return null;
53e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
54e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
55e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public int noteOp(Context context, String op, int uid, String packageName) {
56e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return MODE_IGNORED;
57e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
58e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
59e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        public int noteProxyOp(Context context, String op, String proxiedPackageName) {
60e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            return MODE_IGNORED;
61e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        }
62e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
63e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
64e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    private static class AppOpsManager23 extends AppOpsManagerImpl {
65e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        @Override
66e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public String permissionToOp(String permission) {
67e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return AppOpsManagerCompat23.permissionToOp(permission);
68e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
69e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
70e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        @Override
71e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public int noteOp(Context context, String op, int uid, String packageName) {
72e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return AppOpsManagerCompat23.noteOp(context, op, uid, packageName);
73e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
74e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
75e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        @Override
76e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        public int noteProxyOp(Context context, String op, String proxiedPackageName) {
77e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            return AppOpsManagerCompat23.noteProxyOp(context, op, proxiedPackageName);
78e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        }
79e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
80e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
81e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    private static final AppOpsManagerImpl IMPL;
82e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    static {
83e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        if (Build.VERSION.SDK_INT >= 23) {
84e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            IMPL = new AppOpsManager23();
85e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        } else {
86e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            IMPL = new AppOpsManagerImpl();
87e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
88e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
89e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
90e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
91e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Gets the app op name associated with a given permission.
92e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     *
93e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param permission The permission.
94e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return The app op associated with the permission or null.
95e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
96e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static String permissionToOp(@NonNull String permission) {
97e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        return IMPL.permissionToOp(permission);
98e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
99e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
100e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
101e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Make note of an application performing an operation.  Note that you must pass
102e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * in both the uid and name of the application to be checked; this function will verify
103e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
104e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * succeeds, the last execution time of the operation for this app will be updated to
105e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * the current time.
106e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param context Your context.
107e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
108e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param uid The user id of the application attempting to perform the operation.
109e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param packageName The name of the application attempting to perform the operation.
110e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
111e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
112e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * causing the app to crash).
113e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
114e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
115e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteOp(@NonNull Context context, @NonNull String op, int uid,
116e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String packageName) {
117e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        return IMPL.noteOp(context, op, uid, packageName);
118e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
119e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
120e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    /**
121e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * Make note of an application performing an operation on behalf of another
122e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * application when handling an IPC. Note that you must pass the package name
123e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * of the application that is being proxied while its UID will be inferred from
124e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * the IPC state; this function will verify that the calling uid and proxied
125e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * package name match, and if not, return {@link #MODE_IGNORED}. If this call
126e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * succeeds, the last execution time of the operation for the proxied app and
127e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * your app will be updated to the current time.
128e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param context Your context.
129e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
130e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param proxiedPackageName The name of the application calling into the proxy application.
131e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
132e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
133e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * causing the app to crash).
134e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
135e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     */
136e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteProxyOp(@NonNull Context context, @NonNull String op,
137e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String proxiedPackageName) {
138e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        return IMPL.noteProxyOp(context, op, proxiedPackageName);
139e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    }
140e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov}
141