1/*
2 * Copyright (C) 2013 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 <mutex>
18#include <binder/AppOpsManager.h>
19#include <binder/Binder.h>
20#include <binder/IServiceManager.h>
21
22#include <utils/SystemClock.h>
23
24namespace android {
25
26namespace {
27
28#if defined(__BRILLO__)
29// Because Brillo has no application model, security policy is managed
30// statically (at build time) with SELinux controls.
31// As a consequence, it also never runs the AppOpsManager service.
32const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
33#else
34const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
35#endif  // defined(__BRILLO__)
36
37}  // namespace
38
39static String16 _appops("appops");
40static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
41static sp<IBinder> gToken;
42
43static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
44    pthread_mutex_lock(&gTokenMutex);
45    if (gToken == NULL || gToken->pingBinder() != NO_ERROR) {
46        gToken = service->getToken(new BBinder());
47    }
48    pthread_mutex_unlock(&gTokenMutex);
49    return gToken;
50}
51
52AppOpsManager::AppOpsManager()
53{
54}
55
56#if defined(__BRILLO__)
57// There is no AppOpsService on Brillo
58sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
59#else
60sp<IAppOpsService> AppOpsManager::getService()
61{
62
63    std::lock_guard<Mutex> scoped_lock(mLock);
64    int64_t startTime = 0;
65    sp<IAppOpsService> service = mService;
66    while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
67        sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
68        if (binder == NULL) {
69            // Wait for the app ops service to come back...
70            if (startTime == 0) {
71                startTime = uptimeMillis();
72                ALOGI("Waiting for app ops service");
73            } else if ((uptimeMillis()-startTime) > 10000) {
74                ALOGW("Waiting too long for app ops service, giving up");
75                service = NULL;
76                break;
77            }
78            sleep(1);
79        } else {
80            service = interface_cast<IAppOpsService>(binder);
81            mService = service;
82        }
83    }
84    return service;
85}
86#endif  // defined(__BRILLO__)
87
88int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
89{
90    sp<IAppOpsService> service = getService();
91    return service != NULL
92            ? service->checkOperation(op, uid, callingPackage)
93            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
94}
95
96int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
97    sp<IAppOpsService> service = getService();
98    return service != NULL
99            ? service->noteOperation(op, uid, callingPackage)
100            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
101}
102
103int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
104    sp<IAppOpsService> service = getService();
105    return service != NULL
106            ? service->startOperation(getToken(service), op, uid, callingPackage)
107            : APP_OPS_MANAGER_UNAVAILABLE_MODE;
108}
109
110void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
111    sp<IAppOpsService> service = getService();
112    if (service != NULL) {
113        service->finishOperation(getToken(service), op, uid, callingPackage);
114    }
115}
116
117void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
118        const sp<IAppOpsCallback>& callback) {
119    sp<IAppOpsService> service = getService();
120    if (service != NULL) {
121        service->startWatchingMode(op, packageName, callback);
122    }
123}
124
125void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
126    sp<IAppOpsService> service = getService();
127    if (service != NULL) {
128        service->stopWatchingMode(callback);
129    }
130}
131
132int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
133    sp<IAppOpsService> service = getService();
134    if (service != NULL) {
135        return service->permissionToOpCode(permission);
136    }
137    return -1;
138}
139
140
141}; // namespace android
142