Prepare AttributionSource to expose to native - native

Separate the internal state of AttributionSource from the
class to make it a simple AIDL we can translate automatically
to native - keeping Java and native parts in sync. This
would allow writing a thin native lib for checking attribution
source permissions which would be used to teach camera and
audio about attributions.

Deinfe an AIDL interface for passing around an attribution
source and opr performing permission checker oprations allowing
native and Java permission checks on attribution chains to be
handled. The Java side permission checker functions are in a dedicated
permisison checker service on top of which sits the PermissionChecker.
We expose similar PermissionChecker native APIs sitting on top
of the same remote interface. The nice thing is that we have
native and Java permisison checkers in sync sharing remoting
code and being close in shape.

For now the PermissionChecker in Java is divorced from the
PermissionManager but in T we will consider how to unify them,
either by an extension object on the PermmissionManager or
APIs on the PermissionManager, or another approach, and then
migrate clients off the PermissionChecker APIs.

Sync app ops were not tracked across multiple binder calls which
prevents moving the permission checks in the system server as
this adds one more hop. Now sync ops are propagated backed the
call stack and only the ops for the package are dispatched to
it and the rest are propagated back to the caller, recursively.

bug: 158792096

Test: atest CtsPermission5TestCases
      atest CtsAppOps2TestCases
      atest CtsPermissionTestCases
      atest CtsPermission2TestCases
      atest CtsPermission3TestCases
      atest CtsPermission4TestCases
      atest CtsPermission5TestCases

Change-Id: I426685ac268bb1ed31ee5d3e40a4c8bae88f99ba
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index a5712b3..3243a6b 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -7,17 +7,43 @@
     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",
+    ],
+    export_static_lib_headers: ["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
+
+// ---------------------------------------------------------------------------