Merge "Prepare AttributionSource to expose to native - native" into sc-dev
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index a5712b3..1ae0a00 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -7,17 +7,42 @@
     default_applicable_licenses: ["frameworks_native_license"],
 }
 
+aidl_interface {
+    name: "framework-permission-aidl",
+    unstable: true,
+    local_include_dir: "aidl",
+    backend: {
+        ndk: {
+            enabled: false
+        }
+    },
+    srcs: [
+        "aidl/android/content/AttributionSourceState.aidl",
+        "aidl/android/permission/IPermissionChecker.aidl",
+    ],
+}
+
 cc_library_shared {
     name: "libpermission",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
     srcs: [
         "AppOpsManager.cpp",
         "IAppOpsCallback.cpp",
         "IAppOpsService.cpp",
+        "android/permission/PermissionChecker.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "libbinder",
-        "liblog",
         "libutils",
+        "libbinder",
+        "libcutils",
+        "liblog",
+    ],
+    static_libs: [
+        "framework-permission-aidl-cpp",
     ],
 }
diff --git a/libs/permission/aidl/android/content/AttributionSourceState.aidl b/libs/permission/aidl/android/content/AttributionSourceState.aidl
new file mode 100644
index 0000000..b6e54bf
--- /dev/null
+++ b/libs/permission/aidl/android/content/AttributionSourceState.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.content;
+
+/**
+ * Payload for the {@link AttributionSource} class needed to interoperate
+ * with different languages.
+ *
+ * {@hide}
+ */
+parcelable AttributionSourceState {
+    /** The UID that is accessing the permission protected data. */
+    int uid;
+    /** The package that is accessing the permission protected data. */
+    @nullable @utf8InCpp String packageName;
+    /** The attribution tag of the app accessing the permission protected data. */
+    @nullable @utf8InCpp String attributionTag;
+    /** Unique token for that source. */
+    @nullable IBinder token;
+    /** Permissions that should be considered revoked regardless if granted. */
+    @nullable @utf8InCpp String[] renouncedPermissions;
+    /** The next app to receive the permission protected data. */
+    // TODO: We use an array as a workaround - the C++ backend doesn't
+    // support referring to the parcelable as it expects ctor/dtor
+    @nullable AttributionSourceState[] next;
+}
diff --git a/libs/permission/aidl/android/permission/IPermissionChecker.aidl b/libs/permission/aidl/android/permission/IPermissionChecker.aidl
new file mode 100644
index 0000000..1f0e32d
--- /dev/null
+++ b/libs/permission/aidl/android/permission/IPermissionChecker.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.permission;
+
+import android.content.AttributionSourceState;
+
+/**
+ * Interface to communicate directly with the permission checker service.
+ */
+interface IPermissionChecker {
+    const int PERMISSION_GRANTED = 0;
+    const int PERMISSION_SOFT_DENIED = 1;
+    const int PERMISSION_HARD_DENIED = 2;
+
+    int checkPermission(String permission, in AttributionSourceState attributionSource,
+            @nullable String message, boolean forDataDelivery, boolean startDataDelivery,
+            boolean fromDatasource);
+
+    void finishDataDelivery(String op, in AttributionSourceState attributionSource);
+
+    int checkOp(int op, in AttributionSourceState attributionSource,
+            String message, boolean forDataDelivery, boolean startDataDelivery);
+}
diff --git a/libs/permission/android/permission/PermissionChecker.cpp b/libs/permission/android/permission/PermissionChecker.cpp
new file mode 100644
index 0000000..a8083ee
--- /dev/null
+++ b/libs/permission/android/permission/PermissionChecker.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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 {
+
+using android::content::AttributionSourceState;
+
+PermissionChecker::PermissionChecker()
+{
+}
+
+sp<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);
+        }
+    }
+    return mService;
+}
+
+PermissionChecker::PermissionResult
+    PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
+        const String16& permission, AttributionSourceState& attributionSource,
+        const String16& message)
+{
+    return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
+            /*forDataDelivery*/ true, /*startDataDelivery*/ false,/*fromDatasource*/ true));
+}
+
+PermissionChecker::PermissionResult
+    PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
+        const String16& permission, AttributionSourceState& attributionSource,
+        const String16& message)
+{
+    return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
+            /*forDataDelivery*/ true, /*startDataDelivery*/ true, /*fromDatasource*/ true));
+}
+
+void PermissionChecker::finishDataDelivery(const String16& op,
+        AttributionSourceState& attributionSource)
+{
+    sp<IPermissionChecker> service = getService();
+    if (service != nullptr) {
+        binder::Status status = service->finishDataDelivery(op, attributionSource);
+        if (!status.isOk()) {
+            ALOGE("finishDataDelivery failed: %s", status.exceptionMessage().c_str());
+        }
+    }
+}
+
+int32_t PermissionChecker::checkPermission(const String16& permission,
+        AttributionSourceState& attributionSource, const String16& message,
+        bool forDataDelivery, bool startDataDelivery, bool fromDatasource)
+{
+    sp<IPermissionChecker> service = getService();
+    if (service != nullptr) {
+        int32_t result;
+        binder::Status status = service->checkPermission(permission, attributionSource, message,
+                forDataDelivery, startDataDelivery, fromDatasource, &result);
+        if (status.isOk()) {
+            return result;
+        }
+        ALOGE("checkPermission failed: %s", status.exceptionMessage().c_str());
+    }
+    return PERMISSION_DENIED;
+}
+
+} // namespace android
diff --git a/libs/permission/include/android/permission/PermissionChecker.h b/libs/permission/include/android/permission/PermissionChecker.h
new file mode 100644
index 0000000..20ab51f
--- /dev/null
+++ b/libs/permission/include/android/permission/PermissionChecker.h
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/content/AttributionSourceState.h>
+#include <android/permission/IPermissionChecker.h>
+
+#include <utils/threads.h>
+
+#include <optional>
+
+#ifdef __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+using android::content::AttributionSourceState;
+using android::permission::IPermissionChecker;
+
+class PermissionChecker
+{
+public:
+
+    enum PermissionResult {
+
+        /**
+         * The permission is granted.
+         */
+        PERMISSION_GRANTED = IPermissionChecker::PERMISSION_GRANTED,
+
+        /**
+         * The permission is denied. Applicable only to runtime and app op permissions.
+         *
+         * Returned when:
+         *   - the runtime permission is granted, but the corresponding app op is denied
+         *       for runtime permissions.
+         *   - the app ops is ignored for app op permissions.
+         *
+         */
+        PERMISSION_SOFT_DENIED = IPermissionChecker::PERMISSION_SOFT_DENIED,
+
+        /**
+         * The permission is denied.
+         *
+         * Returned when:
+         *  - the permission is denied for non app op permissions.
+         *  - the app op is denied or app op is AppOpsManager#MODE_DEFAULT and permission is denied.
+         */
+        PERMISSION_HARD_DENIED = IPermissionChecker::PERMISSION_HARD_DENIED
+    };
+
+    PermissionChecker();
+
+    /**
+     * Checks whether a given data access chain described by the given attribution source
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed. Call this method if you are the datasource which would not blame you for
+     * access to the data since you are the data. Note that the attribution source chain
+     *
+     * NOTE: The attribution source should be for yourself with its next attribution
+     * source being the app that would receive the data from you.
+     *
+     * NOTE: Use this method only for permission checks at the point where you will deliver
+     * the permission protected data to clients.
+     *
+     * @param permission The permission to check.
+     * @param attributionSource The attribution chain to check.
+     * @param message A message describing the reason the permission was checked.
+     * @return The permission check result which is either PERMISSION_GRANTED,
+     *     or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
+     */
+    PermissionChecker::PermissionResult checkPermissionForDataDeliveryFromDatasource(
+            const String16& permission, AttributionSourceState& attributionSource,
+            const String16& message);
+
+   /**
+     * Checks whether a given data access chain described by the given attribution source
+     * has a given permission and whether the app op that corresponds to this permission
+     * is allowed. The app ops are also marked as started. This is useful for long running
+     * permissions like camera and microphone.
+     *
+     * NOTE: The attribution source should be for yourself with its next attribution
+     * source being the app that would receive the data from you.
+     *
+     * NOTE: Use this method only for permission checks at the point where you will deliver
+     * the permission protected data to clients.
+     *
+     * @param permission The permission to check.
+     * @param attributionSource The attribution chain to check.
+     * @param message A message describing the reason the permission was checked.
+     * @return The permission check result which is either PERMISSION_GRANTED,
+     *     or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
+     */
+    PermissionResult checkPermissionForStartDataDeliveryFromDatasource(
+            const String16& permission, AttributionSourceState& attributionSource,
+            const String16& message);
+
+    /**
+     * Finishes an ongoing op for data access chain described by the given
+     * attribution source.
+     *
+     * @param op The op to finish.
+     * @param attributionSource The attribution chain for which to finish data delivery.
+     */
+    void finishDataDelivery(const String16& op, AttributionSourceState& attributionSource);
+
+private:
+    Mutex mLock;
+    sp<IPermissionChecker> mService;
+    sp<IPermissionChecker> getService();
+
+    int32_t checkPermission(const String16& permission, AttributionSourceState& attributionSource,
+            const String16& message, bool forDataDelivery, bool startDataDelivery,
+            bool fromDatasource);
+};
+
+
+} // namespace android
+
+// ---------------------------------------------------------------------------