libbinder->libpermission: appops

Since libbinder is used in many places, lightening it up (vtables in
these classes contribute to private dirty memory).

Bug: 183654927
Test: boot
Change-Id: I79aa34c023074862c6c568be1f8e3503cd4a24eb
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index 9492bda..dd38224 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -1,5 +1,14 @@
-// TODO(b/183654927): empty place holder to start moving permission related things out of libbinder
-// (appops, permission controller, etc..)
 cc_library_shared {
     name: "libpermission",
+    srcs: [
+        "AppOpsManager.cpp",
+        "IAppOpsCallback.cpp",
+        "IAppOpsService.cpp",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
 }
diff --git a/libs/permission/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
new file mode 100644
index 0000000..f3ea1a7
--- /dev/null
+++ b/libs/permission/AppOpsManager.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 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 <binder/AppOpsManager.h>
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/SystemClock.h>
+
+#include <sys/types.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "AppOpsManager"
+
+namespace android {
+
+static const sp<IBinder>& getClientId() {
+    static pthread_mutex_t gClientIdMutex = PTHREAD_MUTEX_INITIALIZER;
+    static sp<IBinder> gClientId;
+
+    pthread_mutex_lock(&gClientIdMutex);
+    if (gClientId == nullptr) {
+        gClientId = sp<BBinder>::make();
+    }
+    pthread_mutex_unlock(&gClientIdMutex);
+    return gClientId;
+}
+
+AppOpsManager::AppOpsManager()
+{
+}
+
+sp<IAppOpsService> AppOpsManager::getService()
+{
+    static String16 _appops("appops");
+
+    std::lock_guard<Mutex> scoped_lock(mLock);
+    int64_t startTime = 0;
+    sp<IAppOpsService> service = mService;
+    while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
+        sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
+        if (binder == nullptr) {
+            // Wait for the app ops service to come back...
+            if (startTime == 0) {
+                startTime = uptimeMillis();
+                ALOGI("Waiting for app ops service");
+            } else if ((uptimeMillis()-startTime) > 10000) {
+                ALOGW("Waiting too long for app ops service, giving up");
+                service = nullptr;
+                break;
+            }
+            sleep(1);
+        } else {
+            service = interface_cast<IAppOpsService>(binder);
+            mService = service;
+        }
+    }
+    return service;
+}
+
+int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
+{
+    sp<IAppOpsService> service = getService();
+    return service != nullptr
+            ? service->checkOperation(op, uid, callingPackage)
+            : AppOpsManager::MODE_IGNORED;
+}
+
+int32_t AppOpsManager::checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
+        const String16& callingPackage) {
+    sp<IAppOpsService> service = getService();
+    return service != nullptr
+           ? service->checkAudioOperation(op, usage, uid, callingPackage)
+           : AppOpsManager::MODE_IGNORED;
+}
+
+int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
+    return noteOp(op, uid, callingPackage, {},
+            String16("Legacy AppOpsManager.noteOp call"));
+}
+
+int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+        const std::optional<String16>& attributionTag, const String16& message) {
+    sp<IAppOpsService> service = getService();
+    int32_t mode = service != nullptr
+            ? service->noteOperation(op, uid, callingPackage, attributionTag,
+                    shouldCollectNotes(op), message)
+            : AppOpsManager::MODE_IGNORED;
+
+    return mode;
+}
+
+int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+        bool startIfModeDefault) {
+    return startOpNoThrow(op, uid, callingPackage, startIfModeDefault, {},
+            String16("Legacy AppOpsManager.startOpNoThrow call"));
+}
+
+int32_t AppOpsManager::startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+        bool startIfModeDefault, const std::optional<String16>& attributionTag,
+        const String16& message) {
+    sp<IAppOpsService> service = getService();
+    int32_t mode = service != nullptr
+            ? service->startOperation(getClientId(), op, uid, callingPackage,
+                    attributionTag, startIfModeDefault, shouldCollectNotes(op), message)
+            : AppOpsManager::MODE_IGNORED;
+
+    return mode;
+}
+
+void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
+    finishOp(op, uid, callingPackage, {});
+}
+
+void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage,
+        const std::optional<String16>& attributionTag) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        service->finishOperation(getClientId(), op, uid, callingPackage, attributionTag);
+    }
+}
+
+void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
+        const sp<IAppOpsCallback>& callback) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        service->startWatchingMode(op, packageName, callback);
+    }
+}
+
+void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        service->stopWatchingMode(callback);
+    }
+}
+
+int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        return service->permissionToOpCode(permission);
+    }
+    return -1;
+}
+
+void AppOpsManager::setCameraAudioRestriction(int32_t mode) {
+    sp<IAppOpsService> service = getService();
+    if (service != nullptr) {
+        service->setCameraAudioRestriction(mode);
+    }
+}
+
+// check it the appops needs to be collected and cache result
+bool AppOpsManager::shouldCollectNotes(int32_t opcode) {
+    // Whether an appop should be collected: 0 == not initialized, 1 == don't note, 2 == note
+    static uint8_t appOpsToNote[AppOpsManager::_NUM_OP] = {0};
+
+    if (appOpsToNote[opcode] == 0) {
+        if (getService()->shouldCollectNotes(opcode)) {
+            appOpsToNote[opcode] = 2;
+        } else {
+            appOpsToNote[opcode] = 1;
+        }
+    }
+
+    return appOpsToNote[opcode] == 2;
+}
+
+} // namespace android
diff --git a/libs/permission/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp
new file mode 100644
index 0000000..2b3f462
--- /dev/null
+++ b/libs/permission/IAppOpsCallback.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "AppOpsCallback"
+
+#include <binder/IAppOpsCallback.h>
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpAppOpsCallback : public BpInterface<IAppOpsCallback>
+{
+public:
+    explicit BpAppOpsCallback(const sp<IBinder>& impl)
+        : BpInterface<IAppOpsCallback>(impl)
+    {
+    }
+
+    virtual void opChanged(int32_t op, const String16& packageName) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsCallback::getInterfaceDescriptor());
+        data.writeInt32(op);
+        data.writeString16(packageName);
+        remote()->transact(OP_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback")
+
+// ----------------------------------------------------------------------
+
+// NOLINTNEXTLINE(google-default-arguments)
+status_t BnAppOpsCallback::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case OP_CHANGED_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsCallback, data, reply);
+            int32_t op = data.readInt32();
+            String16 packageName;
+            (void)data.readString16(&packageName);
+            opChanged(op, packageName);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+} // namespace android
diff --git a/libs/permission/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
new file mode 100644
index 0000000..1af5ab8
--- /dev/null
+++ b/libs/permission/IAppOpsService.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "AppOpsService"
+
+#include <binder/IAppOpsService.h>
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+#include <optional>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpAppOpsService : public BpInterface<IAppOpsService>
+{
+public:
+    explicit BpAppOpsService(const sp<IBinder>& impl)
+        : BpInterface<IAppOpsService>(impl)
+    {
+    }
+
+    virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(code);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        remote()->transact(CHECK_OPERATION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return MODE_ERRORED;
+        return reply.readInt32();
+    }
+
+    virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
+                const std::optional<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
+                const String16& message) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(code);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        data.writeString16(attributionTag);
+        data.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
+        data.writeString16(message);
+        remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return MODE_ERRORED;
+        return reply.readInt32();
+    }
+
+    virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+                const String16& packageName, const std::optional<String16>& attributionTag,
+                bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        data.writeInt32(code);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        data.writeString16(attributionTag);
+        data.writeInt32(startIfModeDefault ? 1 : 0);
+        data.writeInt32(shouldCollectAsyncNotedOp ? 1 : 0);
+        data.writeString16(message);
+        remote()->transact(START_OPERATION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return MODE_ERRORED;
+        return reply.readInt32();
+    }
+
+    virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName, const std::optional<String16>& attributionTag) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(token);
+        data.writeInt32(code);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        data.writeString16(attributionTag);
+        remote()->transact(FINISH_OPERATION_TRANSACTION, data, &reply);
+    }
+
+    virtual void startWatchingMode(int32_t op, const String16& packageName,
+            const sp<IAppOpsCallback>& callback) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(op);
+        data.writeString16(packageName);
+        data.writeStrongBinder(IInterface::asBinder(callback));
+        remote()->transact(START_WATCHING_MODE_TRANSACTION, data, &reply);
+    }
+
+    virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeStrongBinder(IInterface::asBinder(callback));
+        remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply);
+    }
+
+    virtual int32_t permissionToOpCode(const String16& permission) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeString16(permission);
+        remote()->transact(PERMISSION_TO_OP_CODE_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return -1;
+        return reply.readInt32();
+    }
+
+    virtual int32_t checkAudioOperation(int32_t code, int32_t usage,
+            int32_t uid, const String16& packageName) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(code);
+        data.writeInt32(usage);
+        data.writeInt32(uid);
+        data.writeString16(packageName);
+        remote()->transact(CHECK_AUDIO_OPERATION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) {
+            return MODE_ERRORED;
+        }
+        return reply.readInt32();
+    }
+
+    virtual void setCameraAudioRestriction(int32_t mode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(mode);
+        remote()->transact(SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION, data, &reply);
+    }
+
+    virtual bool shouldCollectNotes(int32_t opCode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeInt32(opCode);
+        remote()->transact(SHOULD_COLLECT_NOTES_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) {
+            return false;
+        }
+        return reply.readBool();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService")
+
+// ----------------------------------------------------------------------
+
+// NOLINTNEXTLINE(google-default-arguments)
+status_t BnAppOpsService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    //printf("AppOpsService received: "); data.print();
+    switch(code) {
+        case CHECK_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            int32_t code = data.readInt32();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            int32_t res = checkOperation(code, uid, packageName);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case NOTE_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            int32_t code = data.readInt32();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            std::optional<String16> attributionTag;
+            data.readString16(&attributionTag);
+            bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
+            String16 message = data.readString16();
+            int32_t res = noteOperation(code, uid, packageName, attributionTag,
+                    shouldCollectAsyncNotedOp, message);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case START_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            int32_t code = data.readInt32();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            std::optional<String16> attributionTag;
+            data.readString16(&attributionTag);
+            bool startIfModeDefault = data.readInt32() == 1;
+            bool shouldCollectAsyncNotedOp = data.readInt32() == 1;
+            String16 message = data.readString16();
+            int32_t res = startOperation(token, code, uid, packageName, attributionTag,
+                    startIfModeDefault, shouldCollectAsyncNotedOp, message);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case FINISH_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IBinder> token = data.readStrongBinder();
+            int32_t code = data.readInt32();
+            int32_t uid = data.readInt32();
+            String16 packageName = data.readString16();
+            std::optional<String16> attributionTag;
+            data.readString16(&attributionTag);
+            finishOperation(token, code, uid, packageName, attributionTag);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case START_WATCHING_MODE_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            int32_t op = data.readInt32();
+            String16 packageName = data.readString16();
+            sp<IAppOpsCallback> callback = interface_cast<IAppOpsCallback>(data.readStrongBinder());
+            startWatchingMode(op, packageName, callback);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case STOP_WATCHING_MODE_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            sp<IAppOpsCallback> callback = interface_cast<IAppOpsCallback>(data.readStrongBinder());
+            stopWatchingMode(callback);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case PERMISSION_TO_OP_CODE_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            String16 permission = data.readString16();
+            const int32_t opCode = permissionToOpCode(permission);
+            reply->writeNoException();
+            reply->writeInt32(opCode);
+            return NO_ERROR;
+        } break;
+        case CHECK_AUDIO_OPERATION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            const int32_t code = data.readInt32();
+            const int32_t usage = data.readInt32();
+            const int32_t uid = data.readInt32();
+            const String16 packageName = data.readString16();
+            const int32_t res = checkAudioOperation(code, usage, uid, packageName);
+            reply->writeNoException();
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        case SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            const int32_t mode = data.readInt32();
+            setCameraAudioRestriction(mode);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case SHOULD_COLLECT_NOTES_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            int32_t opCode = data.readInt32();
+            bool shouldCollect = shouldCollectNotes(opCode);
+            reply->writeNoException();
+            reply->writeBool(shouldCollect);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+} // namespace android
diff --git a/libs/permission/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
new file mode 100644
index 0000000..35c697e
--- /dev/null
+++ b/libs/permission/include/binder/AppOpsManager.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 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 <binder/IAppOpsService.h>
+
+#include <utils/threads.h>
+
+#include <optional>
+
+#ifdef __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class AppOpsManager
+{
+public:
+    enum {
+        MODE_ALLOWED = IAppOpsService::MODE_ALLOWED,
+        MODE_IGNORED = IAppOpsService::MODE_IGNORED,
+        MODE_ERRORED = IAppOpsService::MODE_ERRORED
+    };
+
+    enum {
+        OP_NONE = -1,
+        OP_COARSE_LOCATION = 0,
+        OP_FINE_LOCATION = 1,
+        OP_GPS = 2,
+        OP_VIBRATE = 3,
+        OP_READ_CONTACTS = 4,
+        OP_WRITE_CONTACTS = 5,
+        OP_READ_CALL_LOG = 6,
+        OP_WRITE_CALL_LOG = 7,
+        OP_READ_CALENDAR = 8,
+        OP_WRITE_CALENDAR = 9,
+        OP_WIFI_SCAN = 10,
+        OP_POST_NOTIFICATION = 11,
+        OP_NEIGHBORING_CELLS = 12,
+        OP_CALL_PHONE = 13,
+        OP_READ_SMS = 14,
+        OP_WRITE_SMS = 15,
+        OP_RECEIVE_SMS = 16,
+        OP_RECEIVE_EMERGECY_SMS = 17,
+        OP_RECEIVE_MMS = 18,
+        OP_RECEIVE_WAP_PUSH = 19,
+        OP_SEND_SMS = 20,
+        OP_READ_ICC_SMS = 21,
+        OP_WRITE_ICC_SMS = 22,
+        OP_WRITE_SETTINGS = 23,
+        OP_SYSTEM_ALERT_WINDOW = 24,
+        OP_ACCESS_NOTIFICATIONS = 25,
+        OP_CAMERA = 26,
+        OP_RECORD_AUDIO = 27,
+        OP_PLAY_AUDIO = 28,
+        OP_READ_CLIPBOARD = 29,
+        OP_WRITE_CLIPBOARD = 30,
+        OP_TAKE_MEDIA_BUTTONS = 31,
+        OP_TAKE_AUDIO_FOCUS = 32,
+        OP_AUDIO_MASTER_VOLUME = 33,
+        OP_AUDIO_VOICE_VOLUME = 34,
+        OP_AUDIO_RING_VOLUME = 35,
+        OP_AUDIO_MEDIA_VOLUME = 36,
+        OP_AUDIO_ALARM_VOLUME = 37,
+        OP_AUDIO_NOTIFICATION_VOLUME = 38,
+        OP_AUDIO_BLUETOOTH_VOLUME = 39,
+        OP_WAKE_LOCK = 40,
+        OP_MONITOR_LOCATION = 41,
+        OP_MONITOR_HIGH_POWER_LOCATION = 42,
+        OP_GET_USAGE_STATS = 43,
+        OP_MUTE_MICROPHONE = 44,
+        OP_TOAST_WINDOW = 45,
+        OP_PROJECT_MEDIA = 46,
+        OP_ACTIVATE_VPN = 47,
+        OP_WRITE_WALLPAPER = 48,
+        OP_ASSIST_STRUCTURE = 49,
+        OP_ASSIST_SCREENSHOT = 50,
+        OP_READ_PHONE_STATE = 51,
+        OP_ADD_VOICEMAIL = 52,
+        OP_USE_SIP = 53,
+        OP_PROCESS_OUTGOING_CALLS = 54,
+        OP_USE_FINGERPRINT = 55,
+        OP_BODY_SENSORS = 56,
+        OP_AUDIO_ACCESSIBILITY_VOLUME = 64,
+        OP_READ_PHONE_NUMBERS = 65,
+        OP_REQUEST_INSTALL_PACKAGES = 66,
+        OP_PICTURE_IN_PICTURE = 67,
+        OP_INSTANT_APP_START_FOREGROUND = 68,
+        OP_ANSWER_PHONE_CALLS = 69,
+        OP_RUN_ANY_IN_BACKGROUND = 70,
+        OP_CHANGE_WIFI_STATE = 71,
+        OP_REQUEST_DELETE_PACKAGES = 72,
+        OP_BIND_ACCESSIBILITY_SERVICE = 73,
+        OP_ACCEPT_HANDOVER = 74,
+        OP_MANAGE_IPSEC_TUNNELS = 75,
+        OP_START_FOREGROUND = 76,
+        OP_BLUETOOTH_SCAN = 77,
+        OP_USE_BIOMETRIC = 78,
+        OP_ACTIVITY_RECOGNITION = 79,
+        OP_SMS_FINANCIAL_TRANSACTIONS = 80,
+        OP_READ_MEDIA_AUDIO = 81,
+        OP_WRITE_MEDIA_AUDIO = 82,
+        OP_READ_MEDIA_VIDEO = 83,
+        OP_WRITE_MEDIA_VIDEO = 84,
+        OP_READ_MEDIA_IMAGES = 85,
+        OP_WRITE_MEDIA_IMAGES = 86,
+        OP_LEGACY_STORAGE = 87,
+        OP_ACCESS_ACCESSIBILITY = 88,
+        OP_READ_DEVICE_IDENTIFIERS = 89,
+        OP_ACCESS_MEDIA_LOCATION = 90,
+        OP_QUERY_ALL_PACKAGES = 91,
+        OP_MANAGE_EXTERNAL_STORAGE = 92,
+        OP_INTERACT_ACROSS_PROFILES = 93,
+        OP_ACTIVATE_PLATFORM_VPN = 94,
+        OP_LOADER_USAGE_STATS = 95,
+        OP_DEPRECATED_1 = 96,
+        OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97,
+        OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98,
+        OP_NO_ISOLATED_STORAGE = 99,
+        OP_PHONE_CALL_MICROPHONE = 100,
+        OP_PHONE_CALL_CAMERA = 101,
+        OP_RECORD_AUDIO_HOTWORD = 102,
+        _NUM_OP = 103
+    };
+
+    AppOpsManager();
+
+    int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
+    int32_t checkAudioOpNoThrow(int32_t op, int32_t usage, int32_t uid,
+            const String16& callingPackage);
+    // @Deprecated, use noteOp(int32_t, int32_t uid, const String16&, const String16&,
+    //              const String16&) instead
+    int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
+    int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage,
+            const std::optional<String16>& attributionTag, const String16& message);
+    // @Deprecated, use startOpNoThrow(int32_t, int32_t, const String16&, bool, const String16&,
+    //              const String16&) instead
+    int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+            bool startIfModeDefault);
+    int32_t startOpNoThrow(int32_t op, int32_t uid, const String16& callingPackage,
+            bool startIfModeDefault, const std::optional<String16>& attributionTag,
+            const String16& message);
+    // @Deprecated, use finishOp(int32_t, int32_t, const String16&, bool, const String16&) instead
+    void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
+    void finishOp(int32_t op, int32_t uid, const String16& callingPackage,
+            const std::optional<String16>& attributionTag);
+    void startWatchingMode(int32_t op, const String16& packageName,
+            const sp<IAppOpsCallback>& callback);
+    void stopWatchingMode(const sp<IAppOpsCallback>& callback);
+    int32_t permissionToOpCode(const String16& permission);
+    void setCameraAudioRestriction(int32_t mode);
+
+private:
+    Mutex mLock;
+    sp<IAppOpsService> mService;
+
+    sp<IAppOpsService> getService();
+    bool shouldCollectNotes(int32_t opCode);
+};
+
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
diff --git a/libs/permission/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h
new file mode 100644
index 0000000..eb76f57
--- /dev/null
+++ b/libs/permission/include/binder/IAppOpsCallback.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2013 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
+
+#ifndef __ANDROID_VNDK__
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IAppOpsCallback : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AppOpsCallback)
+
+    virtual void opChanged(int32_t op, const String16& packageName) = 0;
+
+    enum {
+        OP_CHANGED_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnAppOpsCallback : public BnInterface<IAppOpsCallback>
+{
+public:
+    // NOLINTNEXTLINE(google-default-arguments)
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+} // namespace android
+
+#else // __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif // __ANDROID_VNDK__
diff --git a/libs/permission/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
new file mode 100644
index 0000000..b0719d4
--- /dev/null
+++ b/libs/permission/include/binder/IAppOpsService.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 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 <binder/IAppOpsCallback.h>
+#include <binder/IInterface.h>
+
+#include <optional>
+
+#ifdef __ANDROID_VNDK__
+#error "This header is not visible to vendors"
+#endif
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IAppOpsService : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(AppOpsService)
+
+    virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+    virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName,
+            const std::optional<String16>& attributionTag, bool shouldCollectAsyncNotedOp,
+            const String16& message) = 0;
+    virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName, const std::optional<String16>& attributionTag,
+            bool startIfModeDefault, bool shouldCollectAsyncNotedOp, const String16& message) = 0;
+    virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
+            const String16& packageName, const std::optional<String16>& attributionTag) = 0;
+    virtual void startWatchingMode(int32_t op, const String16& packageName,
+            const sp<IAppOpsCallback>& callback) = 0;
+    virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
+    virtual int32_t permissionToOpCode(const String16& permission) = 0;
+    virtual int32_t checkAudioOperation(int32_t code, int32_t usage,int32_t uid,
+            const String16& packageName) = 0;
+    virtual void setCameraAudioRestriction(int32_t mode) = 0;
+    virtual bool shouldCollectNotes(int32_t opCode) = 0;
+
+    enum {
+        CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+        NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
+        START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
+        FINISH_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+3,
+        START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
+        STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
+        PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
+        CHECK_AUDIO_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
+        SHOULD_COLLECT_NOTES_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+8,
+        SET_CAMERA_AUDIO_RESTRICTION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+9,
+    };
+
+    enum {
+        MODE_ALLOWED = 0,
+        MODE_IGNORED = 1,
+        MODE_ERRORED = 2
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnAppOpsService : public BnInterface<IAppOpsService>
+{
+public:
+    // NOLINTNEXTLINE(google-default-arguments)
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+} // namespace android