diff options
Diffstat (limited to 'libs/permission/android/permission/PermissionChecker.cpp')
-rw-r--r-- | libs/permission/android/permission/PermissionChecker.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/libs/permission/android/permission/PermissionChecker.cpp b/libs/permission/android/permission/PermissionChecker.cpp new file mode 100644 index 0000000000..66526f90ea --- /dev/null +++ b/libs/permission/android/permission/PermissionChecker.cpp @@ -0,0 +1,132 @@ +/* + * 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::checkPermissionForPreflight( + const String16& permission, const AttributionSourceState& attributionSource, + const String16& message, int32_t attributedOpCode) +{ + return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ false, + /*startDataDelivery*/ false, /*fromDatasource*/ false, 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 |