Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9438e62a authored by Mark Wheatley's avatar Mark Wheatley Committed by Android (Google) Code Review
Browse files

Merge changes from topic "hal_bypass_sensor_data_injection-main" into main

* changes:
  Start Wear Debug service in System Server
  Add support for multiple data injection modes in Sensor Manager
parents 93845a69 2c6c7c81
Loading
Loading
Loading
Loading
+74 −5
Original line number Diff line number Diff line
@@ -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
     */
    protected abstract boolean initDataInjectionImpl(boolean enable);
    public boolean initDataInjection(boolean enable, @DataInjectionMode int mode) {
        return initDataInjectionImpl(enable, mode);
    }

    /**
     * @hide
     */
    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");
        }
+45 −6
Original line number Diff line number Diff line
@@ -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) {
+1 −1
Original line number Diff line number Diff line
@@ -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;
        }

+17 −0
Original line number Diff line number Diff line
@@ -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},

+1 −1
Original line number Diff line number Diff line
@@ -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");
    }

Loading