1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.companion.virtual; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.companion.virtual.IVirtualDevice; 22 import android.companion.virtual.sensor.IVirtualSensorCallback; 23 import android.companion.virtual.sensor.VirtualSensor; 24 import android.companion.virtual.sensor.VirtualSensorConfig; 25 import android.companion.virtual.sensor.VirtualSensorEvent; 26 import android.content.AttributionSource; 27 import android.hardware.SensorDirectChannel; 28 import android.os.Binder; 29 import android.os.IBinder; 30 import android.os.ParcelFileDescriptor; 31 import android.os.RemoteException; 32 import android.os.SharedMemory; 33 import android.util.ArrayMap; 34 import android.util.Slog; 35 import android.util.SparseArray; 36 37 import com.android.internal.annotations.GuardedBy; 38 import com.android.internal.annotations.VisibleForTesting; 39 import com.android.modules.expresslog.Counter; 40 import com.android.server.LocalServices; 41 import com.android.server.sensors.SensorManagerInternal; 42 43 import java.io.PrintWriter; 44 import java.util.ArrayList; 45 import java.util.Collections; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.Objects; 49 import java.util.concurrent.atomic.AtomicInteger; 50 51 /** Controls virtual sensors, including their lifecycle and sensor event dispatch. */ 52 public class SensorController { 53 54 private static final String TAG = "SensorController"; 55 56 // See system/core/libutils/include/utils/Errors.h 57 private static final int OK = 0; 58 private static final int UNKNOWN_ERROR = (-2147483647 - 1); // INT32_MIN value 59 private static final int BAD_VALUE = -22; 60 61 private static AtomicInteger sNextDirectChannelHandle = new AtomicInteger(1); 62 63 private final Object mLock = new Object(); 64 private final int mVirtualDeviceId; 65 66 @GuardedBy("mLock") 67 private final ArrayMap<IBinder, SensorDescriptor> mSensorDescriptors = new ArrayMap<>(); 68 69 // This device's sensors, keyed by sensor handle. 70 @GuardedBy("mLock") 71 private SparseArray<VirtualSensor> mVirtualSensors = new SparseArray<>(); 72 @GuardedBy("mLock") 73 private List<VirtualSensor> mVirtualSensorList = null; 74 75 @NonNull 76 private final AttributionSource mAttributionSource; 77 @NonNull 78 private final SensorManagerInternal.RuntimeSensorCallback mRuntimeSensorCallback; 79 private final SensorManagerInternal mSensorManagerInternal; 80 private final VirtualDeviceManagerInternal mVdmInternal; 81 SensorController(@onNull IVirtualDevice virtualDevice, int virtualDeviceId, @NonNull AttributionSource attributionSource, @Nullable IVirtualSensorCallback virtualSensorCallback, @NonNull List<VirtualSensorConfig> sensors)82 public SensorController(@NonNull IVirtualDevice virtualDevice, int virtualDeviceId, 83 @NonNull AttributionSource attributionSource, 84 @Nullable IVirtualSensorCallback virtualSensorCallback, 85 @NonNull List<VirtualSensorConfig> sensors) { 86 mVirtualDeviceId = virtualDeviceId; 87 mAttributionSource = attributionSource; 88 mRuntimeSensorCallback = new RuntimeSensorCallbackWrapper(virtualSensorCallback); 89 mSensorManagerInternal = LocalServices.getService(SensorManagerInternal.class); 90 mVdmInternal = LocalServices.getService(VirtualDeviceManagerInternal.class); 91 createSensors(virtualDevice, sensors); 92 } 93 close()94 void close() { 95 synchronized (mLock) { 96 mSensorDescriptors.values().forEach( 97 descriptor -> mSensorManagerInternal.removeRuntimeSensor(descriptor.mHandle)); 98 mSensorDescriptors.clear(); 99 mVirtualSensors.clear(); 100 mVirtualSensorList = null; 101 } 102 } 103 createSensors(@onNull IVirtualDevice virtualDevice, @NonNull List<VirtualSensorConfig> configs)104 private void createSensors(@NonNull IVirtualDevice virtualDevice, 105 @NonNull List<VirtualSensorConfig> configs) { 106 Objects.requireNonNull(virtualDevice); 107 final long token = Binder.clearCallingIdentity(); 108 try { 109 for (VirtualSensorConfig config : configs) { 110 createSensorInternal(virtualDevice, config); 111 } 112 } catch (SensorCreationException e) { 113 throw new RuntimeException("Failed to create virtual sensor", e); 114 } finally { 115 Binder.restoreCallingIdentity(token); 116 } 117 } 118 createSensorInternal(@onNull IVirtualDevice virtualDevice, @NonNull VirtualSensorConfig config)119 private void createSensorInternal(@NonNull IVirtualDevice virtualDevice, 120 @NonNull VirtualSensorConfig config) 121 throws SensorCreationException { 122 Objects.requireNonNull(config); 123 if (config.getType() <= 0) { 124 throw new SensorCreationException( 125 "Received an invalid virtual sensor type (config name '" + config.getName() 126 + "')."); 127 } 128 final int handle = mSensorManagerInternal.createRuntimeSensor(mVirtualDeviceId, 129 config.getType(), config.getName(), 130 config.getVendor() == null ? "" : config.getVendor(), config.getMaximumRange(), 131 config.getResolution(), config.getPower(), config.getMinDelay(), 132 config.getMaxDelay(), config.getFlags(), mRuntimeSensorCallback); 133 if (handle <= 0) { 134 throw new SensorCreationException( 135 "Received an invalid virtual sensor handle '" + config.getName() + "'."); 136 } 137 138 SensorDescriptor sensorDescriptor = new SensorDescriptor( 139 handle, config.getType(), config.getName()); 140 final IBinder sensorToken = 141 new Binder("android.hardware.sensor.VirtualSensor:" + config.getName()); 142 VirtualSensor sensor = new VirtualSensor(handle, config.getType(), config.getName(), 143 virtualDevice, sensorToken); 144 synchronized (mLock) { 145 mSensorDescriptors.put(sensorToken, sensorDescriptor); 146 mVirtualSensors.put(handle, sensor); 147 } 148 if (android.companion.virtualdevice.flags.Flags.metricsCollection()) { 149 Counter.logIncrementWithUid( 150 "virtual_devices.value_virtual_sensors_created_count", 151 mAttributionSource.getUid()); 152 } 153 } 154 sendSensorEvent(@onNull IBinder token, @NonNull VirtualSensorEvent event)155 boolean sendSensorEvent(@NonNull IBinder token, @NonNull VirtualSensorEvent event) { 156 Objects.requireNonNull(token); 157 Objects.requireNonNull(event); 158 synchronized (mLock) { 159 final SensorDescriptor sensorDescriptor = mSensorDescriptors.get(token); 160 if (sensorDescriptor == null) { 161 throw new IllegalArgumentException("Could not send sensor event for given token"); 162 } 163 return mSensorManagerInternal.sendSensorEvent( 164 sensorDescriptor.getHandle(), sensorDescriptor.getType(), 165 event.getTimestampNanos(), event.getValues()); 166 } 167 } 168 169 @Nullable getSensorByHandle(int handle)170 VirtualSensor getSensorByHandle(int handle) { 171 synchronized (mLock) { 172 return mVirtualSensors.get(handle); 173 } 174 } 175 getSensorList()176 List<VirtualSensor> getSensorList() { 177 synchronized (mLock) { 178 if (mVirtualSensorList == null) { 179 mVirtualSensorList = new ArrayList<>(mVirtualSensors.size()); 180 for (int i = 0; i < mVirtualSensors.size(); ++i) { 181 mVirtualSensorList.add(mVirtualSensors.valueAt(i)); 182 } 183 mVirtualSensorList = Collections.unmodifiableList(mVirtualSensorList); 184 } 185 return mVirtualSensorList; 186 } 187 } 188 dump(@onNull PrintWriter fout)189 void dump(@NonNull PrintWriter fout) { 190 fout.println(" SensorController: "); 191 synchronized (mLock) { 192 fout.println(" Active descriptors: "); 193 for (SensorDescriptor sensorDescriptor : mSensorDescriptors.values()) { 194 fout.println(" handle: " + sensorDescriptor.getHandle()); 195 fout.println(" type: " + sensorDescriptor.getType()); 196 fout.println(" name: " + sensorDescriptor.getName()); 197 } 198 } 199 } 200 201 @VisibleForTesting addSensorForTesting(IBinder deviceToken, int handle, int type, String name)202 void addSensorForTesting(IBinder deviceToken, int handle, int type, String name) { 203 synchronized (mLock) { 204 mSensorDescriptors.put(deviceToken, 205 new SensorDescriptor(handle, type, name)); 206 } 207 } 208 209 @VisibleForTesting getSensorDescriptors()210 Map<IBinder, SensorDescriptor> getSensorDescriptors() { 211 synchronized (mLock) { 212 return new ArrayMap<>(mSensorDescriptors); 213 } 214 } 215 216 private final class RuntimeSensorCallbackWrapper 217 implements SensorManagerInternal.RuntimeSensorCallback { 218 @Nullable 219 private IVirtualSensorCallback mCallback; 220 RuntimeSensorCallbackWrapper(@ullable IVirtualSensorCallback callback)221 RuntimeSensorCallbackWrapper(@Nullable IVirtualSensorCallback callback) { 222 mCallback = callback; 223 } 224 225 @Override onConfigurationChanged(int handle, boolean enabled, int samplingPeriodMicros, int batchReportLatencyMicros)226 public int onConfigurationChanged(int handle, boolean enabled, int samplingPeriodMicros, 227 int batchReportLatencyMicros) { 228 if (mCallback == null) { 229 Slog.e(TAG, "No sensor callback configured for sensor handle " + handle); 230 return BAD_VALUE; 231 } 232 VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, handle); 233 if (sensor == null) { 234 Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId 235 + " and sensor handle=" + handle); 236 return BAD_VALUE; 237 } 238 try { 239 mCallback.onConfigurationChanged(sensor, enabled, samplingPeriodMicros, 240 batchReportLatencyMicros); 241 } catch (RemoteException e) { 242 Slog.e(TAG, "Failed to call sensor callback: " + e); 243 return UNKNOWN_ERROR; 244 } 245 return OK; 246 } 247 248 @Override onDirectChannelCreated(ParcelFileDescriptor fd)249 public int onDirectChannelCreated(ParcelFileDescriptor fd) { 250 if (mCallback == null) { 251 Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId); 252 return BAD_VALUE; 253 } else if (fd == null) { 254 Slog.e(TAG, "Received invalid ParcelFileDescriptor"); 255 return BAD_VALUE; 256 } 257 final int channelHandle = sNextDirectChannelHandle.getAndIncrement(); 258 SharedMemory sharedMemory = SharedMemory.fromFileDescriptor(fd); 259 try { 260 mCallback.onDirectChannelCreated(channelHandle, sharedMemory); 261 } catch (RemoteException e) { 262 Slog.e(TAG, "Failed to call sensor callback: " + e); 263 return UNKNOWN_ERROR; 264 } 265 return channelHandle; 266 } 267 268 @Override onDirectChannelDestroyed(int channelHandle)269 public void onDirectChannelDestroyed(int channelHandle) { 270 if (mCallback == null) { 271 Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId); 272 return; 273 } 274 try { 275 mCallback.onDirectChannelDestroyed(channelHandle); 276 } catch (RemoteException e) { 277 Slog.e(TAG, "Failed to call sensor callback: " + e); 278 } 279 } 280 281 @Override onDirectChannelConfigured(int channelHandle, int sensorHandle, @SensorDirectChannel.RateLevel int rateLevel)282 public int onDirectChannelConfigured(int channelHandle, int sensorHandle, 283 @SensorDirectChannel.RateLevel int rateLevel) { 284 if (mCallback == null) { 285 Slog.e(TAG, "No runtime sensor callback configured."); 286 return BAD_VALUE; 287 } 288 VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, sensorHandle); 289 if (sensor == null) { 290 Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId 291 + " and sensor handle=" + sensorHandle); 292 return BAD_VALUE; 293 } 294 try { 295 mCallback.onDirectChannelConfigured(channelHandle, sensor, rateLevel, sensorHandle); 296 } catch (RemoteException e) { 297 Slog.e(TAG, "Failed to call sensor callback: " + e); 298 return UNKNOWN_ERROR; 299 } 300 if (rateLevel == SensorDirectChannel.RATE_STOP) { 301 return OK; 302 } else { 303 // Use the sensor handle as a report token, i.e. a unique identifier of the sensor. 304 return sensorHandle; 305 } 306 } 307 } 308 309 @VisibleForTesting 310 static final class SensorDescriptor { 311 312 private final int mHandle; 313 private final int mType; 314 private final String mName; 315 SensorDescriptor(int handle, int type, String name)316 SensorDescriptor(int handle, int type, String name) { 317 mHandle = handle; 318 mType = type; 319 mName = name; 320 } getHandle()321 public int getHandle() { 322 return mHandle; 323 } getType()324 public int getType() { 325 return mType; 326 } getName()327 public String getName() { 328 return mName; 329 } 330 } 331 332 /** An internal exception that is thrown to indicate an error when opening a virtual sensor. */ 333 private static class SensorCreationException extends Exception { SensorCreationException(String message)334 SensorCreationException(String message) { 335 super(message); 336 } 337 } 338 } 339