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

Commit fa2672b7 authored by Peng Xu's avatar Peng Xu
Browse files

Sensor event direct report mode implementation

Implementation of sensor direct report API. In this verison, only
ashmem(MemoryFile) backed direct channel is implemented. Support
of HardwareBuffer class will come in a following CL.

Test: tested with demo app
Bug: 30985702
Change-Id: I29cae5cb2615c7a128fe203ed1545c03010ca4aa
parent ccf0c8ed
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -737,6 +737,14 @@ public final class Sensor {
    private static final int ADDITIONAL_INFO_MASK = 0x40;
    private static final int ADDITIONAL_INFO_SHIFT = 6;

    // Mask for direct mode highest rate level, bit 7, 8, 9.
    private static final int DIRECT_REPORT_MASK = 0x380;
    private static final int DIRECT_REPORT_SHIFT = 7;

    // Mask for supported direct channel, bit 10, 11
    private static final int DIRECT_CHANNEL_MASK = 0xC00;
    private static final int DIRECT_CHANNEL_SHIFT = 10;

    // TODO(): The following arrays are fragile and error-prone. This needs to be refactored.

    // Note: This needs to be updated, whenever a new sensor is added.
@@ -808,7 +816,9 @@ public final class Sensor {
     */
    @SensorDirectChannel.RateLevel
    public int getHighestDirectReportRateLevel() {
        return SensorDirectChannel.RATE_STOP;
        int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
        return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
                ? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
    }

    /**
@@ -820,8 +830,15 @@ public final class Sensor {
     * @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
     */
    public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
        switch (sharedMemType) {
            case SensorDirectChannel.TYPE_ASHMEM:
                return (mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0;
            case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
                return (mFlags & (1 << DIRECT_CHANNEL_SHIFT + 1)) > 0;
            default:
                return false;
        }
    }

    static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
        // RotationVector length has changed to 3 to 5 for API level 18
+27 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ public final class SensorDirectChannel implements AutoCloseable {
     * @return <code>true</code> if channel is valid.
     */
    public boolean isValid() {
        return false;
        return !mClosed.get();
    }

    /**
@@ -123,9 +123,32 @@ public final class SensorDirectChannel implements AutoCloseable {
    /** @hide */
    SensorDirectChannel(SensorManager manager, int id, int type, long size) {
        mManager = manager;
        mNativeHandle = id;
        mType = type;
        mSize = size;
        mCloseGuard.open("SensorDirectChannel");
    }

    /** @hide */
    int getNativeHandle() {
        return mNativeHandle;
    }

    /**
     * This function encode handle information in {@link android.os.Memory} into a long array to be
     * passed down to native methods.
     *
     * @hide */
    static long[] encodeData(MemoryFile ashmem) {
        int fd;
        try {
            fd = ashmem.getFileDescriptor().getInt$();
        } catch (IOException e) {
            fd = -1;
        }
        return new long[] { 1 /*numFds*/, 0 /*numInts*/, fd };
    }

    @Override
    protected void finalize() throws Throwable {
        try {
@@ -139,4 +162,7 @@ public final class SensorDirectChannel implements AutoCloseable {
    private final AtomicBoolean mClosed = new AtomicBoolean();
    private final CloseGuard mCloseGuard = CloseGuard.get();
    private final SensorManager mManager;
    private final int mNativeHandle;
    private final long mSize;
    private final int mType;
}
+14 −2
Original line number Diff line number Diff line
@@ -895,7 +895,7 @@ public abstract class SensorManager {
     * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
     */
    public SensorDirectChannel createDirectChannel(MemoryFile mem) {
        return null;
        return createDirectChannelImpl(mem.length(), mem, null);
    }

    /**
@@ -916,10 +916,18 @@ public abstract class SensorManager {
        return null;
    }

    /** @hide */
    protected abstract SensorDirectChannel createDirectChannelImpl(long size,
            MemoryFile ashmemFile, HardwareBuffer hardwareBuffer);

    /** @hide */
    void destroyDirectChannel(SensorDirectChannel channel) {
        destroyDirectChannelImpl(channel);
    }

    /** @hide */
    protected abstract void destroyDirectChannelImpl(SensorDirectChannel channel);

    /**
     * Configure sensor rate or stop sensor report on a direct report channel specified.
     *
@@ -964,9 +972,13 @@ public abstract class SensorManager {
     */
    public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor,
            @SensorDirectChannel.RateLevel int rateLevel) {
        return 0;
        return configureDirectChannelImpl(channel, sensor, rateLevel);
    }

    /** @hide */
    protected abstract int configureDirectChannelImpl(
            SensorDirectChannel channel, Sensor s, int rate);

    /**
     * Used for receiving notifications from the SensorManager when dynamic sensors are connected or
     * disconnected.
+73 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.Looper;
import android.os.MemoryFile;
import android.os.MessageQueue;
import android.util.Log;
import android.util.SparseArray;
@@ -57,6 +58,13 @@ public class SystemSensorManager extends SensorManager {
    private static native void nativeGetDynamicSensors(long nativeInstance, List<Sensor> list);
    private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);

    private static native int nativeCreateDirectChannel(
            long nativeInstance, long size, int channelType, long [] channelData);
    private static native void nativeDestroyDirectChannel(
            long nativeInstance, int channelHandle);
    private static native int nativeConfigDirectChannel(
            long nativeInstance, int channelHandle, int sensorHandle, int rate);

    private static final Object sLock = new Object();
    @GuardedBy("sLock")
    private static boolean sNativeClassInited = false;
@@ -484,6 +492,71 @@ public class SystemSensorManager extends SensorManager {
        return changed;
    }

    /** @hide */
    protected int configureDirectChannelImpl(
            SensorDirectChannel channel, Sensor sensor, int rate) {
        if (channel == null) throw new IllegalArgumentException("channel cannot be null");

        if (!channel.isValid()) {
            throw new IllegalStateException("channel is invalid");
        }

        if (rate < SensorDirectChannel.RATE_STOP
                || rate > SensorDirectChannel.RATE_VERY_FAST) {
            throw new IllegalArgumentException("rate parameter invalid");
        }

        if (sensor == null && rate != SensorDirectChannel.RATE_STOP) {
            // the stop all sensors case
            throw new IllegalArgumentException(
                    "when sensor is null, rate can only be DIRECT_RATE_STOP");
        }

        int sensorHandle = (sensor == null) ? -1 : sensor.getHandle();

        int ret = nativeConfigDirectChannel(
                mNativeInstance, channel.getNativeHandle(), sensorHandle, rate);

        if (rate == SensorDirectChannel.RATE_STOP) {
            return (ret == 0) ? 1 : 0;
        } else {
            return (ret > 0) ? ret : 0;
        }
    }

    /** @hide */
    protected SensorDirectChannel createDirectChannelImpl(long size,
            MemoryFile ashmemFile, HardwareBuffer grallocMemObject) {
        SensorDirectChannel ch = null;

        if (size <= 0) throw new IllegalArgumentException("size has to be greater than 0");

        if (ashmemFile != null) {
            if (size != ashmemFile.length()) {
                throw new IllegalArgumentException("size has to match MemoryFile.length()");
            }
            int id = nativeCreateDirectChannel(
                    mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM,
                    SensorDirectChannel.encodeData(ashmemFile));
            if (id > 0) {
                ch = new SensorDirectChannel(this, id, SensorDirectChannel.TYPE_ASHMEM, size);
            }
        } else if (grallocMemObject != null) {
            Log.wtf(TAG, "Implement GRALLOC or remove GRALLOC support entirely");
        } else {
            throw new IllegalArgumentException("Invalid parameter");
        }

        return ch;
    }

    /** @hide */
    protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
        if (channel != null) {
            nativeDestroyDirectChannel(mNativeInstance, channel.getNativeHandle());
        }
    }

    /*
     * BaseEventQueue is the communication channel with the sensor service,
     * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
+62 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <gui/Sensor.h>
#include <gui/SensorEventQueue.h>
#include <gui/SensorManager.h>
#include <cutils/native_handle.h>
#include <utils/Log.h>
#include <utils/Looper.h>
#include <utils/Vector.h>
@@ -243,6 +244,54 @@ static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong s
    return mgr->isDataInjectionEnabled();
}

static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
        jlong size, jint channelType, jlongArray channelData) {
    jint ret = -1;
    jsize len = _env->GetArrayLength(channelData);
    if (len > 2) {
        jlong *data = _env->GetLongArrayElements(channelData, NULL);
        if (data != nullptr) {
            // construct native handle from jlong*
            jlong numFd = data[0];
            jlong numInt = data[1];
            if ((numFd + numInt + 2) == len) {
                native_handle_t *nativeHandle = native_handle_create(numFd, numInt);
                if (nativeHandle != nullptr) {
                    const jlong *readPointer = data + 2;
                    int *writePointer = nativeHandle->data;
                    size_t n = static_cast<size_t>(numFd + numInt);
                    while (n--) {
                        // native type of data is int, jlong is just to ensure Java does not
                        // truncate data on 64-bit system. The cast here is safe.
                        *writePointer++ = static_cast<int>(*readPointer++);
                    }

                    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
                    ret = mgr->createDirectChannel(size, channelType, nativeHandle);

                    // do not native_handle_close() here as handle is owned by java
                    native_handle_delete(nativeHandle);
                }
            }
            // unidirectional parameter passing, thus JNI_ABORT
            _env->ReleaseLongArrayElements(channelData, data, JNI_ABORT);
        }
    }
    return ret;
}

static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
        jint channelHandle) {
    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    mgr->destroyDirectChannel(channelHandle);
}

static jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
        jint channelHandle, jint sensorHandle, jint rate) {
    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
}

//----------------------------------------------------------------------------

class Receiver : public LooperCallback {
@@ -448,6 +497,18 @@ static const JNINativeMethod gSystemSensorManagerMethods[] = {
    {"nativeIsDataInjectionEnabled",
            "(J)Z",
            (void*)nativeIsDataInjectionEnabled },

    {"nativeCreateDirectChannel",
            "(JJI[J)I",
            (void*)nativeCreateDirectChannel },

    {"nativeDestroyDirectChannel",
            "(JI)V",
            (void*)nativeDestroyDirectChannel },

    {"nativeConfigDirectChannel",
            "(JIII)I",
            (void*)nativeConfigDirectChannel },
};

static const JNINativeMethod gBaseEventQueueMethods[] = {