blob: 008afad607d06c93f9777d9e9af4a4c88a3cb959 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <mutex>
#include <include/android/permission/PermissionChecker.h>
#include <binder/Binder.h>
#include <binder/IServiceManager.h>
#include <utils/SystemClock.h>
#include <sys/types.h>
#include <private/android_filesystem_config.h>
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "PermissionChecker"
namespace android::permission {
using android::content::AttributionSourceState;
PermissionChecker::PermissionChecker()
{
}
sp<android::permission::IPermissionChecker> PermissionChecker::getService()
{
static String16 permission_checker("permission_checker");
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
sp<IPermissionChecker> service = mService;
while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(permission_checker);
if (binder == nullptr) {
// Wait for the permission checker service to come back...
if (startTime == 0) {
startTime = uptimeMillis();
ALOGW("Waiting for permission checker service");
} else if ((uptimeMillis() - startTime) > 10000) {
ALOGE("Waiting too long for permission checker service, giving up");
service = nullptr;
break;
}
sleep(1);
} else {
mService = interface_cast<IPermissionChecker>(binder);
break;
}
}
return mService;
}
PermissionChecker::PermissionResult PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
const String16& permission, const AttributionSourceState& attributionSource,
const String16& message, int32_t attributedOpCode)
{
return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
/*startDataDelivery*/ false,/*fromDatasource*/ true, attributedOpCode);
}
PermissionChecker::PermissionResult
PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
const String16& permission, const AttributionSourceState& attributionSource,
const String16& message, int32_t attributedOpCode)
{
return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
/*startDataDelivery*/ true, /*fromDatasource*/ true, attributedOpCode);
}
PermissionChecker::PermissionResult PermissionChecker::checkPermissionForPreflightFromDatasource(
const String16& permission, const AttributionSourceState& attributionSource,
const String16& message, int32_t attributedOpCode)
{
return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ false,
/*startDataDelivery*/ false, /*fromDatasource*/ true, attributedOpCode);
}
void PermissionChecker::finishDataDeliveryFromDatasource(int32_t op,
const AttributionSourceState& attributionSource)
{
sp<IPermissionChecker> service = getService();
if (service != nullptr) {
binder::Status status = service->finishDataDelivery(op, attributionSource,
/*fromDatasource*/ true);
if (!status.isOk()) {
ALOGE("finishDataDelivery failed: %s", status.exceptionMessage().c_str());
}
}
}
PermissionChecker::PermissionResult PermissionChecker::checkPermission(const String16& permission,
const AttributionSourceState& attributionSource, const String16& message,
bool forDataDelivery, bool startDataDelivery, bool fromDatasource,
int32_t attributedOpCode)
{
sp<IPermissionChecker> service = getService();
if (service != nullptr) {
int32_t result;
binder::Status status = service->checkPermission(permission, attributionSource, message,
forDataDelivery, startDataDelivery, fromDatasource, attributedOpCode, &result);
if (status.isOk()) {
return static_cast<PermissionResult>(result);
}
ALOGE("checkPermission failed: %s", status.exceptionMessage().c_str());
}
return PERMISSION_HARD_DENIED;
}
} // namespace android::permission