Merge "App ops: new native access API."
diff --git a/include/binder/AppOpsManager.h b/include/binder/AppOpsManager.h
new file mode 100644
index 0000000..f64d5da
--- /dev/null
+++ b/include/binder/AppOpsManager.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.
+ */
+
+#ifndef ANDROID_APP_OPS_MANAGER_H
+#define ANDROID_APP_OPS_MANAGER_H
+
+#include <binder/IAppOpsService.h>
+
+#include <utils/threads.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class AppOpsManager
+{
+public:
+ enum {
+ MODE_ALLOWED = 0,
+ MODE_IGNORED = 1,
+ MODE_ERRORED = 2
+ };
+
+ 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
+ };
+
+ AppOpsManager();
+
+ int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
+ int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
+ int32_t startOp(int32_t op, int32_t uid, const String16& callingPackage);
+ void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
+ void startWatchingMode(int32_t op, const String16& packageName,
+ const sp<IAppOpsCallback>& callback);
+ void stopWatchingMode(const sp<IAppOpsCallback>& callback);
+
+private:
+ Mutex mLock;
+ sp<IAppOpsService> mService;
+
+ sp<IAppOpsService> getService();
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_APP_OPS_MANAGER_H
diff --git a/include/binder/IAppOpsCallback.h b/include/binder/IAppOpsCallback.h
new file mode 100644
index 0000000..7f8eb01
--- /dev/null
+++ b/include/binder/IAppOpsCallback.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+//
+#ifndef ANDROID_IAPP_OPS_CALLBACK_H
+#define ANDROID_IAPP_OPS_CALLBACK_H
+
+#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:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAPP_OPS_CALLBACK_H
+
diff --git a/include/binder/IAppOpsService.h b/include/binder/IAppOpsService.h
new file mode 100644
index 0000000..2883e38
--- /dev/null
+++ b/include/binder/IAppOpsService.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+//
+#ifndef ANDROID_IAPP_OPS_SERVICE_H
+#define ANDROID_IAPP_OPS_SERVICE_H
+
+#include <binder/IAppOpsCallback.h>
+#include <binder/IInterface.h>
+
+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) = 0;
+ virtual int32_t startOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+ virtual void finishOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
+ virtual void startWatchingMode(int32_t op, const String16& packageName,
+ const sp<IAppOpsCallback>& callback) = 0;
+ virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 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
+ };
+};
+
+// ----------------------------------------------------------------------
+
+class BnAppOpsService : public BnInterface<IAppOpsService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IAPP_OPS_SERVICE_H
+
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index d449298..994d3db 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -14,8 +14,11 @@
# we have the common sources, plus some device-specific stuff
sources := \
+ AppOpsManager.cpp \
Binder.cpp \
BpBinder.cpp \
+ IAppOpsCallback.cpp \
+ IAppOpsService.cpp \
IInterface.cpp \
IMemory.cpp \
IPCThreadState.cpp \
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
new file mode 100644
index 0000000..5d36dd2
--- /dev/null
+++ b/libs/binder/AppOpsManager.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 <binder/AppOpsManager.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/SystemClock.h>
+
+namespace android {
+
+static String16 _appops("appops");
+
+AppOpsManager::AppOpsManager()
+{
+}
+
+sp<IAppOpsService> AppOpsManager::getService()
+{
+ int64_t startTime = 0;
+ mLock.lock();
+ sp<IAppOpsService> service = mService;
+ while (true) {
+ if (service == NULL || !service->asBinder()->isBinderAlive()) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
+ if (binder == NULL) {
+ // 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");
+ return NULL;
+ }
+ sleep(1);
+ } else {
+ service = interface_cast<IAppOpsService>(binder);
+ mService = service;
+ }
+ }
+ }
+ mLock.unlock();
+ return service;
+}
+
+int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
+{
+ sp<IAppOpsService> service = getService();
+ return service != NULL ? service->checkOperation(op, uid, callingPackage) : MODE_IGNORED;
+}
+
+int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
+ sp<IAppOpsService> service = getService();
+ return service != NULL ? service->noteOperation(op, uid, callingPackage) : MODE_IGNORED;
+}
+
+int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
+ sp<IAppOpsService> service = getService();
+ return service != NULL ? service->startOperation(op, uid, callingPackage) : MODE_IGNORED;
+}
+
+void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
+ sp<IAppOpsService> service = getService();
+ if (service != NULL) {
+ service->finishOperation(op, uid, callingPackage);
+ }
+}
+
+void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
+ const sp<IAppOpsCallback>& callback) {
+ sp<IAppOpsService> service = getService();
+ if (service != NULL) {
+ service->startWatchingMode(op, packageName, callback);
+ }
+}
+
+void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
+ sp<IAppOpsService> service = getService();
+ if (service != NULL) {
+ service->stopWatchingMode(callback);
+ }
+}
+
+}; // namespace android
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/binder/IAppOpsCallback.cpp
new file mode 100644
index 0000000..e0aad23
--- /dev/null
+++ b/libs/binder/IAppOpsCallback.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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/Debug.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+#include <private/binder/Static.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpAppOpsCallback : public BpInterface<IAppOpsCallback>
+{
+public:
+ 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);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback");
+
+// ----------------------------------------------------------------------
+
+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 = data.readString16();
+ opChanged(op, packageName);
+ reply->writeNoException();
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/libs/binder/IAppOpsService.cpp b/libs/binder/IAppOpsService.cpp
new file mode 100644
index 0000000..d8922c9
--- /dev/null
+++ b/libs/binder/IAppOpsService.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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/Debug.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+#include <private/binder/Static.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpAppOpsService : public BpInterface<IAppOpsService>
+{
+public:
+ 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 0;
+ return reply.readInt32() != 0;
+ }
+
+ virtual int32_t noteOperation(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(NOTE_OPERATION_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return 0;
+ return reply.readInt32() != 0;
+ }
+
+ virtual int32_t startOperation(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(START_OPERATION_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return 0;
+ return reply.readInt32() != 0;
+ }
+
+ virtual void finishOperation(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(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(callback->asBinder());
+ remote()->transact(START_WATCHING_MODE_TRANSACTION, data, &reply);
+ }
+
+ virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+ data.writeStrongBinder(callback->asBinder());
+ remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
+
+// ----------------------------------------------------------------------
+
+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();
+ int32_t res = noteOperation(code, uid, packageName);
+ reply->writeNoException();
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
+ case START_OPERATION_TRANSACTION: {
+ CHECK_INTERFACE(IAppOpsService, data, reply);
+ int32_t code = data.readInt32();
+ int32_t uid = data.readInt32();
+ String16 packageName = data.readString16();
+ int32_t res = startOperation(code, uid, packageName);
+ reply->writeNoException();
+ reply->writeInt32(res);
+ return NO_ERROR;
+ } break;
+ case FINISH_OPERATION_TRANSACTION: {
+ CHECK_INTERFACE(IAppOpsService, data, reply);
+ int32_t code = data.readInt32();
+ int32_t uid = data.readInt32();
+ String16 packageName = data.readString16();
+ finishOperation(code, uid, packageName);
+ 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;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android