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 */
27c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banespublic final 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 {
51552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas        AppOpsManagerImpl() {
52552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas        }
53552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas
54e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public String permissionToOp(String permission) {
55e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return null;
56e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
57e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
58e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public int noteOp(Context context, String op, int uid, String packageName) {
59e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return MODE_IGNORED;
60e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
61e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
62e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        public int noteProxyOp(Context context, String op, String proxiedPackageName) {
63e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            return MODE_IGNORED;
64e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        }
65e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
66e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
67e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    private static class AppOpsManager23 extends AppOpsManagerImpl {
68552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas        AppOpsManager23() {
69552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas        }
70552766fa685c63ad760c92239faaba12e6ad51f1Aurimas Liutikas
71e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        @Override
72e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public String permissionToOp(String permission) {
73e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return AppOpsManagerCompat23.permissionToOp(permission);
74e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
75e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
76e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        @Override
77e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        public int noteOp(Context context, String op, int uid, String packageName) {
78e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            return AppOpsManagerCompat23.noteOp(context, op, uid, packageName);
79e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
80e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
81e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        @Override
82e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        public int noteProxyOp(Context context, String op, String proxiedPackageName) {
83e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            return AppOpsManagerCompat23.noteProxyOp(context, op, proxiedPackageName);
84e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        }
85e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
86e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
87e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    private static final AppOpsManagerImpl IMPL;
88e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    static {
89e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        if (Build.VERSION.SDK_INT >= 23) {
90e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            IMPL = new AppOpsManager23();
91e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        } else {
92e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov            IMPL = new AppOpsManagerImpl();
93e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        }
94e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
95e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
96c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes    private AppOpsManagerCompat() {}
97c5847d13e40f5d52459f5c0dab32dc08f1a9a683Chris Banes
98e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
99e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Gets the app op name associated with a given permission.
100e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     *
101e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param permission The permission.
102e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return The app op associated with the permission or null.
103e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
104e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    public static String permissionToOp(@NonNull String permission) {
105e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        return IMPL.permissionToOp(permission);
106e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
107e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov
108e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    /**
109e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * Make note of an application performing an operation.  Note that you must pass
110e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * in both the uid and name of the application to be checked; this function will verify
111e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * that these two match, and if not, return {@link #MODE_IGNORED}.  If this call
112e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * succeeds, the last execution time of the operation for this app will be updated to
113e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * the current time.
114e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param context Your context.
115e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
116e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param uid The user id of the application attempting to perform the operation.
117e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @param packageName The name of the application attempting to perform the operation.
118e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
119e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
120e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * causing the app to crash).
121e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
122e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov     */
123e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteOp(@NonNull Context context, @NonNull String op, int uid,
124e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String packageName) {
125e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov        return IMPL.noteOp(context, op, uid, packageName);
126e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov    }
127e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov
128e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    /**
129e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * Make note of an application performing an operation on behalf of another
130e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * application when handling an IPC. Note that you must pass the package name
131e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * of the application that is being proxied while its UID will be inferred from
132e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * the IPC state; this function will verify that the calling uid and proxied
133e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * package name match, and if not, return {@link #MODE_IGNORED}. If this call
134e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * succeeds, the last execution time of the operation for the proxied app and
135e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * your app will be updated to the current time.
136e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param context Your context.
137e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param op The operation to note.  One of the OPSTR_* constants.
138e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @param proxiedPackageName The name of the application calling into the proxy application.
139e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
140e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
141e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * causing the app to crash).
142e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     * @throws SecurityException If the app has been configured to crash on this op.
143e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov     */
144e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    public static int noteProxyOp(@NonNull Context context, @NonNull String op,
145e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov            @NonNull String proxiedPackageName) {
146e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov        return IMPL.noteProxyOp(context, op, proxiedPackageName);
147e899df75f63baf0669f3cbdb193c7475979c8122Svet Ganov    }
148e2458f312876e3f9ac64f0155997ab21b2b906f2Svet Ganov}
149