ServiceUtilities.cpp revision be71aa29a3c86d2e01cd17839d2a72ab09a1bce5
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
17#include <binder/AppOpsManager.h>
18#include <binder/IPCThreadState.h>
19#include <binder/IServiceManager.h>
20#include <binder/PermissionCache.h>
21#include "ServiceUtilities.h"
22
23/* When performing permission checks we do not use permission cache for
24 * runtime permissions (protection level dangerous) as they may change at
25 * runtime. All other permissions (protection level normal and dangerous)
26 * can be cached as they never change. Of course all permission checked
27 * here are platform defined.
28 */
29
30namespace android {
31
32// Not valid until initialized by AudioFlinger constructor.  It would have to be
33// re-initialized if the process containing AudioFlinger service forks (which it doesn't).
34pid_t getpid_cached;
35
36bool recordingAllowed(const String16& opPackageName) {
37    // Note: We are getting the UID from the calling IPC thread state because all
38    // clients that perform recording create AudioRecord in their own processes
39    // and the system does not create AudioRecord objects on behalf of apps. This
40    // differs from playback where in some situations the system recreates AudioTrack
41    // instances associated with a client's MediaPlayer on behalf of this client.
42    // In the latter case we have to store the client UID and pass in along for
43    // security checks.
44
45    if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
46    static const String16 sRecordAudio("android.permission.RECORD_AUDIO");
47
48    // IMPORTANT: Don't use PermissionCache - a runtime permission and may change.
49    const bool ok = checkCallingPermission(sRecordAudio);
50    if (!ok) {
51        ALOGE("Request requires android.permission.RECORD_AUDIO");
52        return false;
53    }
54
55    const uid_t uid = IPCThreadState::self()->getCallingUid();
56    String16 checkedOpPackageName = opPackageName;
57
58    // In some cases the calling code has no access to the package it runs under.
59    // For example, code using the wilhelm framework's OpenSL-ES APIs. In this
60    // case we will get the packages for the calling UID and pick the first one
61    // for attributing the app op. This will work correctly for runtime permissions
62    // as for legacy apps we will toggle the app op for all packages in the UID.
63    // The caveat is that the operation may be attributed to the wrong package and
64    // stats based on app ops may be slightly off.
65    if (checkedOpPackageName.size() <= 0) {
66        sp<IServiceManager> sm = defaultServiceManager();
67        sp<IBinder> binder = sm->getService(String16("permission"));
68        if (binder == 0) {
69            ALOGE("Cannot get permission service");
70            return false;
71        }
72
73        sp<IPermissionController> permCtrl = interface_cast<IPermissionController>(binder);
74        Vector<String16> packages;
75
76        permCtrl->getPackagesForUid(uid, packages);
77
78        if (packages.isEmpty()) {
79            ALOGE("No packages for calling UID");
80            return false;
81        }
82        checkedOpPackageName = packages[0];
83    }
84
85    AppOpsManager appOps;
86    if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, opPackageName)
87            != AppOpsManager::MODE_ALLOWED) {
88        ALOGE("Request denied by app op OP_RECORD_AUDIO");
89        return false;
90    }
91
92    return true;
93}
94
95bool captureAudioOutputAllowed() {
96    if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
97    static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
98    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
99    bool ok = PermissionCache::checkCallingPermission(sCaptureAudioOutput);
100    if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
101    return ok;
102}
103
104bool captureHotwordAllowed() {
105    static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD");
106    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
107    bool ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed);
108    if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD");
109    return ok;
110}
111
112bool settingsAllowed() {
113    if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
114    static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
115    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
116    bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
117    if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
118    return ok;
119}
120
121bool modifyAudioRoutingAllowed() {
122    static const String16 sModifyAudioRoutingAllowed("android.permission.MODIFY_AUDIO_ROUTING");
123    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
124    bool ok = PermissionCache::checkCallingPermission(sModifyAudioRoutingAllowed);
125    if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING");
126    return ok;
127}
128
129bool dumpAllowed() {
130    // don't optimize for same pid, since mediaserver never dumps itself
131    static const String16 sDump("android.permission.DUMP");
132    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
133    bool ok = PermissionCache::checkCallingPermission(sDump);
134    // convention is for caller to dump an error message to fd instead of logging here
135    //if (!ok) ALOGE("Request requires android.permission.DUMP");
136    return ok;
137}
138
139} // namespace android
140