No sensor access to idle UIDs - native framework
Idle UIDs are ones that were in the background for long enough time.
Currently such apps can access sensor data even though they have no
user perceptible components running. This affects the user's privacy
since an app in the background can use sensor data to infer location,
activity, habits, etc.
The goal is to restrict sensor access for all apps in the ecosystem
regardless of target SDK which means the solution should be backwards
compatible. At the high level the sesnor service observes UID state
changes and applies policy like this:
Continuous sensors: for sensros in this reporting mode when the UID
goes in the background we will stop dispatching events. Once the UID
goes active we will start reporting the events. While this is an
app visible behavior change we would rather do that vs delivering
fake events.
Flush events: there is no change in behavior based on the UID state.
Hence, idle apps can request a flush and would get the completion
callback. From an app perspective flushing works at any point.
Trigger events: for sensors in this reporting mode when the UID
goes in the background we will not report any trigger events. From
an app perspective the sensor just did not pick up any events.
On-change events: for sensors in this reporting mode when the UID
goes in the background we will not report any change events. From
an app perspective the sensor just did not pick up any events.
Wake locks: since UIDs in idle state cannot acquire wakelocks we
will not be grabbing a wakelock on behalf of apps in that state.
Test: Added - SensorTest#testSanitizedContinuousEventsUidIdle
Added - SensorTest#testBatchAndFlushUidIdle
Pass - cts-tradefed run cts-dev -m CtsSensorTestCases
bug:63938985
Change-Id: I156803610ad6d86afaae641ebbb0e84f16d2344b
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2a07cd1..1dd1e6a 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -63,6 +63,7 @@
"MemoryHeapBase.cpp",
"Parcel.cpp",
"PermissionCache.cpp",
+ "PermissionController.cpp",
"PersistableBundle.cpp",
"ProcessInfoService.cpp",
"ProcessState.cpp",
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index 674bddf..ef67ab8 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -78,6 +78,18 @@
if (reply.readExceptionCode() != 0) return false;
return reply.readInt32() != 0;
}
+
+ virtual int getPackageUid(const String16& package, int flags)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+ data.writeString16(package);
+ data.writeInt32(flags);
+ remote()->transact(GET_PACKAGE_UID_TRANSACTION, data, &reply);
+ // fail on exception
+ if (reply.readExceptionCode() != 0) return false;
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
@@ -122,6 +134,16 @@
return NO_ERROR;
} break;
+ case GET_PACKAGE_UID_TRANSACTION: {
+ CHECK_INTERFACE(IPermissionController, data, reply);
+ String16 package = data.readString16();
+ int flags = data.readInt32();
+ const int uid = getPackageUid(package, flags);
+ reply->writeNoException();
+ reply->writeInt32(uid);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/PermissionController.cpp b/libs/binder/PermissionController.cpp
new file mode 100644
index 0000000..25748ca
--- /dev/null
+++ b/libs/binder/PermissionController.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 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/PermissionController.h>
+#include <binder/Binder.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/SystemClock.h>
+
+namespace android {
+
+PermissionController::PermissionController()
+{
+}
+
+sp<IPermissionController> PermissionController::getService()
+{
+ std::lock_guard<Mutex> scoped_lock(mLock);
+ int64_t startTime = 0;
+ sp<IPermissionController> service = mService;
+ while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(String16("permission"));
+ if (binder == nullptr) {
+ // Wait for the activity service to come back...
+ if (startTime == 0) {
+ startTime = uptimeMillis();
+ ALOGI("Waiting for permission service");
+ } else if ((uptimeMillis() - startTime) > 10000) {
+ ALOGW("Waiting too long for permission service, giving up");
+ service = NULL;
+ break;
+ }
+ sleep(1);
+ } else {
+ service = interface_cast<IPermissionController>(binder);
+ mService = service;
+ }
+ }
+ return service;
+}
+
+bool PermissionController::checkPermission(const String16& permission, int32_t pid, int32_t uid)
+{
+ sp<IPermissionController> service = getService();
+ return service != NULL ? service->checkPermission(permission, pid, uid) : false;
+}
+
+void PermissionController::getPackagesForUid(const uid_t uid, Vector<String16> &packages)
+{
+ sp<IPermissionController> service = getService();
+ if (service != nullptr) {
+ service->getPackagesForUid(uid, packages);
+ }
+}
+
+bool PermissionController::isRuntimePermission(const String16& permission)
+{
+ sp<IPermissionController> service = getService();
+ return service != nullptr ? service->isRuntimePermission(permission) : false;
+}
+
+int PermissionController::getPackageUid(const String16& package, int flags)
+{
+ sp<IPermissionController> service = getService();
+ return service != nullptr ? service->getPackageUid(package, flags) : -1;
+}
+
+}; // namespace android
diff --git a/libs/binder/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
index 25f3431..2f63677 100644
--- a/libs/binder/include/binder/IPermissionController.h
+++ b/libs/binder/include/binder/IPermissionController.h
@@ -36,10 +36,13 @@
virtual bool isRuntimePermission(const String16& permission) = 0;
+ virtual int getPackageUid(const String16& package, int flags) = 0;
+
enum {
CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
- IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
+ IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2,
+ GET_PACKAGE_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 3
};
};
diff --git a/libs/binder/include/binder/PermissionController.h b/libs/binder/include/binder/PermissionController.h
new file mode 100644
index 0000000..c4c98d0
--- /dev/null
+++ b/libs/binder/include/binder/PermissionController.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 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_PERMISSION_CONTROLLER_H
+#define ANDROID_PERMISSION_CONTROLLER_H
+
+#include <binder/IPermissionController.h>
+
+#include <utils/threads.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+class PermissionController
+{
+public:
+
+ enum {
+ MATCH_SYSTEM_ONLY = 1<<16,
+ MATCH_UNINSTALLED_PACKAGES = 1<<13,
+ MATCH_FACTORY_ONLY = 1<<21,
+ MATCH_INSTANT = 1<<23
+ };
+
+ PermissionController();
+
+ bool checkPermission(const String16& permission, int32_t pid, int32_t uid);
+ void getPackagesForUid(const uid_t uid, Vector<String16>& packages);
+ bool isRuntimePermission(const String16& permission);
+ int getPackageUid(const String16& package, int flags);
+
+private:
+ Mutex mLock;
+ sp<IPermissionController> mService;
+
+ sp<IPermissionController> getService();
+};
+
+
+}; // namespace android
+// ---------------------------------------------------------------------------
+#endif // ANDROID_PERMISSION_CONTROLLER_H
diff --git a/libs/sensor/ISensorServer.cpp b/libs/sensor/ISensorServer.cpp
index efbbf7d..5200545 100644
--- a/libs/sensor/ISensorServer.cpp
+++ b/libs/sensor/ISensorServer.cpp
@@ -27,6 +27,7 @@
#include <binder/Parcel.h>
#include <binder/IInterface.h>
+#include <binder/IResultReceiver.h>
#include <sensor/Sensor.h>
#include <sensor/ISensorEventConnection.h>
@@ -227,6 +228,30 @@
reply->writeInt32(ret);
return NO_ERROR;
}
+ case SHELL_COMMAND_TRANSACTION: {
+ int in = data.readFileDescriptor();
+ int out = data.readFileDescriptor();
+ int err = data.readFileDescriptor();
+ int argc = data.readInt32();
+ Vector<String16> args;
+ for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+ args.add(data.readString16());
+ }
+ sp<IBinder> unusedCallback;
+ sp<IResultReceiver> resultReceiver;
+ status_t status;
+ if ((status = data.readNullableStrongBinder(&unusedCallback)) != NO_ERROR) {
+ return status;
+ }
+ if ((status = data.readNullableStrongBinder(&resultReceiver)) != NO_ERROR) {
+ return status;
+ }
+ status = shellCommand(in, out, err, args);
+ if (resultReceiver != nullptr) {
+ resultReceiver->send(status);
+ }
+ return NO_ERROR;
+ }
}
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/sensor/include/sensor/ISensorServer.h b/libs/sensor/include/sensor/ISensorServer.h
index edf3e0f..402678f 100644
--- a/libs/sensor/include/sensor/ISensorServer.h
+++ b/libs/sensor/include/sensor/ISensorServer.h
@@ -60,6 +60,9 @@
class BnSensorServer : public BnInterface<ISensorServer>
{
public:
+ virtual status_t shellCommand(int in, int out, int err,
+ Vector<String16>& args) = 0;
+
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,