Respect deviceId in SensorManager cache.
Do not use the cached SensorManager if the device association
of the underlying package has changed.
Since the SensorManager is cached per package, if the deviceId
changes, then the native SensorManager will always return the wrong
sensors. This is seen in the failing CTS.
The most straight-forward solution is to refresh the cache when the
device for that UID has changed. It would be better to have an API
that takes a deviceId but that's a longer term fix - b/306575095
This change is effectively flagged by the read-only flag
android.companion.virtual.flags.enable_native_vdm. When it is
disabled, the deviceId will always be 0 (i.e. default device).
Test: atest VirtualSensorNativeTest
Bug: 306575095
Fix: 317495754
Change-Id: If02beb9f3eceec19c104ae03fcb0a8fefb46f85f
diff --git a/libs/sensor/SensorManager.cpp b/libs/sensor/SensorManager.cpp
index f8ee3fc..b82a79f 100644
--- a/libs/sensor/SensorManager.cpp
+++ b/libs/sensor/SensorManager.cpp
@@ -88,49 +88,51 @@
SensorManager* sensorManager;
auto iterator = sPackageInstances.find(packageName);
+ const uid_t uid = IPCThreadState::self()->getCallingUid();
+ const int deviceId = getDeviceIdForUid(uid);
+
+ // Return the cached instance if the device association of the package has not changed.
if (iterator != sPackageInstances.end()) {
sensorManager = iterator->second;
- } else {
- String16 opPackageName = packageName;
- const uid_t uid = IPCThreadState::self()->getCallingUid();
-
- // It is possible that the calling code has no access to the package name.
- // In this case we will get the packages for the calling UID and pick the
- // first one for attributing the app op. This will work correctly for
- // runtime permissions as for legacy apps we will toggle the app op for
- // all packages in the UID. The caveat is that the operation may be attributed
- // to the wrong package and stats based on app ops may be slightly off.
- if (opPackageName.size() <= 0) {
- sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
- if (binder != nullptr) {
- Vector<String16> packages;
- interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
- if (!packages.isEmpty()) {
- opPackageName = packages[0];
- } else {
- ALOGE("No packages for calling UID");
- }
- } else {
- ALOGE("Cannot get permission service");
- }
+ if (sensorManager->mDeviceId == deviceId) {
+ return *sensorManager;
}
-
- // Check if the calling UID is observed on a virtual device. If so, provide that device's
- // sensors by default instead of the default device's sensors.
- const int deviceId = getDeviceIdForUid(uid);
- sensorManager = new SensorManager(opPackageName, deviceId);
-
- // If we had no package name, we looked it up from the UID and the sensor
- // manager instance we created should also be mapped to the empty package
- // name, to avoid looking up the packages for a UID and get the same result.
- if (packageName.size() <= 0) {
- sPackageInstances.insert(std::make_pair(String16(), sensorManager));
- }
-
- // Stash the per package sensor manager.
- sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
}
+ // It is possible that the calling code has no access to the package name.
+ // In this case we will get the packages for the calling UID and pick the
+ // first one for attributing the app op. This will work correctly for
+ // runtime permissions as for legacy apps we will toggle the app op for
+ // all packages in the UID. The caveat is that the operation may be attributed
+ // to the wrong package and stats based on app ops may be slightly off.
+ String16 opPackageName = packageName;
+ if (opPackageName.size() <= 0) {
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("permission"));
+ if (binder != nullptr) {
+ Vector<String16> packages;
+ interface_cast<IPermissionController>(binder)->getPackagesForUid(uid, packages);
+ if (!packages.isEmpty()) {
+ opPackageName = packages[0];
+ } else {
+ ALOGE("No packages for calling UID");
+ }
+ } else {
+ ALOGE("Cannot get permission service");
+ }
+ }
+
+ sensorManager = new SensorManager(opPackageName, deviceId);
+
+ // If we had no package name, we looked it up from the UID and the sensor
+ // manager instance we created should also be mapped to the empty package
+ // name, to avoid looking up the packages for a UID and get the same result.
+ if (packageName.size() <= 0) {
+ sPackageInstances.insert(std::make_pair(String16(), sensorManager));
+ }
+
+ // Stash the per package sensor manager.
+ sPackageInstances.insert(std::make_pair(opPackageName, sensorManager));
+
return *sensorManager;
}