diff options
7 files changed, 147 insertions, 14 deletions
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index f033f9740b3d..bcf447b4267d 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -16,6 +16,7 @@ package android.hardware; +import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -27,6 +28,8 @@ import android.os.MemoryFile; import android.util.Log; import android.util.SparseArray; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -1809,6 +1812,41 @@ public abstract class SensorManager { protected abstract boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor, boolean disable); + /** + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({DATA_INJECTION, REPLAY_DATA_INJECTION, HAL_BYPASS_REPLAY_DATA_INJECTION}) + public @interface DataInjectionMode {} + /** + * This mode is only used for testing purposes. Not all HALs support this mode. In this mode, + * the HAL ignores the sensor data provided by physical sensors and accepts the data that is + * injected from the SensorService as if it were the real sensor data. This mode is primarily + * used for testing various algorithms like vendor provided SensorFusion, Step Counter and + * Step Detector etc. Typically, in this mode, there is a client app which injects + * sensor data into the HAL. Normal apps can register and unregister for any sensor + * that supports injection. Registering to sensors that do not support injection will + * give an error. + * This is the default data injection mode. + * @hide + */ + public static final int DATA_INJECTION = 1; + /** + * Mostly equivalent to DATA_INJECTION with the difference being that the injected data is + * delivered to all requesting apps rather than just the package allowed to inject data. + * This mode is only allowed to be used on development builds. + * @hide + */ + public static final int REPLAY_DATA_INJECTION = 3; + /** + * Like REPLAY_DATA_INJECTION but injected data is not sent into the HAL. It is stored in a + * buffer in the platform and played back to all requesting apps. + * This is useful for playing back sensor data to test platform components without + * relying on the HAL to support data injection. + * @hide + */ + public static final int HAL_BYPASS_REPLAY_DATA_INJECTION = 4; + /** * For testing purposes only. Not for third party applications. @@ -1833,13 +1871,47 @@ public abstract class SensorManager { */ @SystemApi public boolean initDataInjection(boolean enable) { - return initDataInjectionImpl(enable); + return initDataInjectionImpl(enable, DATA_INJECTION); + } + + /** + * For testing purposes only. Not for third party applications. + * + * Initialize data injection mode and create a client for data injection. SensorService should + * already be operating in one of DATA_INJECTION, REPLAY_DATA_INJECTION or + * HAL_BYPASS_REPLAY_DATA_INJECTION modes for this call succeed. To set SensorService in + * a Data Injection mode, use one of: + * + * <ul> + * <li>adb shell dumpsys sensorservice data_injection</li> + * <li>adb shell dumpsys sensorservice replay_data_injection package_name</li> + * <li>adb shell dumpsys sensorservice hal_bypass_replay_data_injection package_name</li> + * </ul> + * + * Typically this is done using a host side test. This mode is expected to be used + * only for testing purposes. See {@link DataInjectionMode} for details of each data injection + * mode. Once this method succeeds, the test can call + * {@link #injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL. + * To put SensorService back into normal mode, use "adb shell dumpsys sensorservice enable" + * + * @param enable True to initialize a client in a data injection mode. + * False to clean up the native resources. + * + * @param mode One of DATA_INJECTION, REPLAY_DATA_INJECTION or HAL_BYPASS_DATA_INJECTION. + * See {@link DataInjectionMode} for details. + * + * @return true if the HAL supports data injection and false + * otherwise. + * @hide + */ + public boolean initDataInjection(boolean enable, @DataInjectionMode int mode) { + return initDataInjectionImpl(enable, mode); } /** * @hide */ - protected abstract boolean initDataInjectionImpl(boolean enable); + protected abstract boolean initDataInjectionImpl(boolean enable, @DataInjectionMode int mode); /** * For testing purposes only. Not for third party applications. @@ -1871,9 +1943,6 @@ public abstract class SensorManager { if (sensor == null) { throw new IllegalArgumentException("sensor cannot be null"); } - if (!sensor.isDataInjectionSupported()) { - throw new IllegalArgumentException("sensor does not support data injection"); - } if (values == null) { throw new IllegalArgumentException("sensor data cannot be null"); } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index dfd380233662..40e03dbb8b34 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -90,6 +90,8 @@ public class SystemSensorManager extends SensorManager { private static native void nativeGetRuntimeSensors( long nativeInstance, int deviceId, List<Sensor> list); private static native boolean nativeIsDataInjectionEnabled(long nativeInstance); + private static native boolean nativeIsReplayDataInjectionEnabled(long nativeInstance); + private static native boolean nativeIsHalBypassReplayDataInjectionEnabled(long nativeInstance); private static native int nativeCreateDirectChannel( long nativeInstance, int deviceId, long size, int channelType, int fd, @@ -384,20 +386,41 @@ public class SystemSensorManager extends SensorManager { } } - protected boolean initDataInjectionImpl(boolean enable) { + protected boolean initDataInjectionImpl(boolean enable, @DataInjectionMode int mode) { synchronized (sLock) { + boolean isDataInjectionModeEnabled = false; if (enable) { - boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance); + switch (mode) { + case DATA_INJECTION: + isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance); + break; + case REPLAY_DATA_INJECTION: + isDataInjectionModeEnabled = nativeIsReplayDataInjectionEnabled( + mNativeInstance); + break; + case HAL_BYPASS_REPLAY_DATA_INJECTION: + isDataInjectionModeEnabled = nativeIsHalBypassReplayDataInjectionEnabled( + mNativeInstance); + break; + default: + break; + } // The HAL does not support injection OR SensorService hasn't been set in DI mode. if (!isDataInjectionModeEnabled) { - Log.e(TAG, "Data Injection mode not enabled"); + Log.e(TAG, "The correct Data Injection mode has not been enabled"); return false; } + if (sInjectEventQueue != null && sInjectEventQueue.getDataInjectionMode() != mode) { + // The inject event queue has been initialized for a different type of DI + // close it and create a new one + sInjectEventQueue.dispose(); + sInjectEventQueue = null; + } // Initialize a client for data_injection. if (sInjectEventQueue == null) { try { sInjectEventQueue = new InjectEventQueue( - mMainLooper, this, mContext.getPackageName()); + mMainLooper, this, mode, mContext.getPackageName()); } catch (RuntimeException e) { Log.e(TAG, "Cannot create InjectEventQueue: " + e); } @@ -421,6 +444,12 @@ public class SystemSensorManager extends SensorManager { Log.e(TAG, "Data injection mode not activated before calling injectSensorData"); return false; } + if (sInjectEventQueue.getDataInjectionMode() != HAL_BYPASS_REPLAY_DATA_INJECTION + && !sensor.isDataInjectionSupported()) { + // DI mode and Replay DI mode require support from the sensor HAL + // HAL Bypass mode doesn't require this. + throw new IllegalArgumentException("sensor does not support data injection"); + } int ret = sInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy, timestamp); // If there are any errors in data injection clean up the native resources. @@ -825,6 +854,8 @@ public class SystemSensorManager extends SensorManager { protected static final int OPERATING_MODE_NORMAL = 0; protected static final int OPERATING_MODE_DATA_INJECTION = 1; + protected static final int OPERATING_MODE_REPLAY_DATA_INJECTION = 3; + protected static final int OPERATING_MODE_HAL_BYPASS_REPLAY_DATA_INJECTION = 4; BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) { if (packageName == null) packageName = ""; @@ -1134,8 +1165,12 @@ public class SystemSensorManager extends SensorManager { } final class InjectEventQueue extends BaseEventQueue { - public InjectEventQueue(Looper looper, SystemSensorManager manager, String packageName) { - super(looper, manager, OPERATING_MODE_DATA_INJECTION, packageName); + + private int mMode; + public InjectEventQueue(Looper looper, SystemSensorManager manager, + @DataInjectionMode int mode, String packageName) { + super(looper, manager, mode, packageName); + mMode = mode; } int injectSensorData(int handle, float[] values, int accuracy, long timestamp) { @@ -1161,6 +1196,10 @@ public class SystemSensorManager extends SensorManager { protected void removeSensorEvent(Sensor sensor) { } + + int getDataInjectionMode() { + return mMode; + } } protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) { diff --git a/core/java/android/hardware/input/InputDeviceSensorManager.java b/core/java/android/hardware/input/InputDeviceSensorManager.java index aa55e543dd48..05024ea95eda 100644 --- a/core/java/android/hardware/input/InputDeviceSensorManager.java +++ b/core/java/android/hardware/input/InputDeviceSensorManager.java @@ -644,7 +644,7 @@ public class InputDeviceSensorManager implements InputManager.InputDeviceListene } @Override - protected boolean initDataInjectionImpl(boolean enable) { + protected boolean initDataInjectionImpl(boolean enable, int mode) { return false; } diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp index deb138fda867..9c883d18a9ae 100644 --- a/core/jni/android_hardware_SensorManager.cpp +++ b/core/jni/android_hardware_SensorManager.cpp @@ -265,6 +265,18 @@ static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong s return mgr->isDataInjectionEnabled(); } +static jboolean nativeIsReplayDataInjectionEnabled(JNIEnv *_env, jclass _this, + jlong sensorManager) { + SensorManager *mgr = reinterpret_cast<SensorManager *>(sensorManager); + return mgr->isReplayDataInjectionEnabled(); +} + +static jboolean nativeIsHalBypassReplayDataInjectionEnabled(JNIEnv *_env, jclass _this, + jlong sensorManager) { + SensorManager *mgr = reinterpret_cast<SensorManager *>(sensorManager); + return mgr->isHalBypassReplayDataInjectionEnabled(); +} + static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager, jint deviceId, jlong size, jint channelType, jint fd, jobject hardwareBufferObj) { @@ -533,6 +545,11 @@ static const JNINativeMethod gSystemSensorManagerMethods[] = { {"nativeIsDataInjectionEnabled", "(J)Z", (void *)nativeIsDataInjectionEnabled}, + {"nativeIsReplayDataInjectionEnabled", "(J)Z", (void *)nativeIsReplayDataInjectionEnabled}, + + {"nativeIsHalBypassReplayDataInjectionEnabled", "(J)Z", + (void *)nativeIsHalBypassReplayDataInjectionEnabled}, + {"nativeCreateDirectChannel", "(JIJIILandroid/hardware/HardwareBuffer;)I", (void *)nativeCreateDirectChannel}, diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java index 9b06a37e681f..d56672564f6f 100644 --- a/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java +++ b/packages/SystemUI/src/com/android/systemui/util/sensors/AsyncSensorManager.java @@ -191,7 +191,7 @@ public class AsyncSensorManager extends SensorManager } @Override - protected boolean initDataInjectionImpl(boolean enable) { + protected boolean initDataInjectionImpl(boolean enable, @DataInjectionMode int mode) { throw new UnsupportedOperationException("not implemented"); } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/FakeSensorManager.java b/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/FakeSensorManager.java index 197873f15d0d..288dcfe2825d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/FakeSensorManager.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/sensors/FakeSensorManager.java @@ -186,7 +186,7 @@ public class FakeSensorManager extends SensorManager { } @Override - protected boolean initDataInjectionImpl(boolean enable) { + protected boolean initDataInjectionImpl(boolean enable, @DataInjectionMode int mode) { return false; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index c26aee8af83e..924e2f8ec654 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -338,6 +338,8 @@ public final class SystemServer implements Dumpable { "com.android.clockwork.modes.ModeManagerService"; private static final String WEAR_DISPLAY_SERVICE_CLASS = "com.android.clockwork.display.WearDisplayService"; + private static final String WEAR_DEBUG_SERVICE_CLASS = + "com.android.clockwork.debug.WearDebugService"; private static final String WEAR_TIME_SERVICE_CLASS = "com.android.clockwork.time.WearTimeService"; private static final String WEAR_SETTINGS_SERVICE_CLASS = @@ -2636,6 +2638,12 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(WEAR_DISPLAY_SERVICE_CLASS); t.traceEnd(); + if (Build.IS_DEBUGGABLE) { + t.traceBegin("StartWearDebugService"); + mSystemServiceManager.startService(WEAR_DEBUG_SERVICE_CLASS); + t.traceEnd(); + } + t.traceBegin("StartWearTimeService"); mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS); t.traceEnd(); |