diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a8f377da26862..d87c55e1c7c79 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -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,7 +830,14 @@ public final class Sensor {
* @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
*/
public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
- return false;
+ 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) {
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index fa4ab4e286689..0efd62b463f8f 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -99,7 +99,7 @@ public final class SensorDirectChannel implements AutoCloseable {
* @return true 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;
}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ad59b55ea2819..cfda2f4fa8b48 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -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.
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 259ca032918b7..4992def7de152 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -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 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
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 271f24b130524..bc2fc1c398906 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -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(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(*readPointer++);
+ }
+
+ SensorManager* mgr = reinterpret_cast(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);
+ mgr->destroyDirectChannel(channelHandle);
+}
+
+static jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
+ jint channelHandle, jint sensorHandle, jint rate) {
+ SensorManager* mgr = reinterpret_cast(sensorManager);
+ return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
+}
+
//----------------------------------------------------------------------------
class Receiver : public LooperCallback {
@@ -447,7 +496,19 @@ static const JNINativeMethod gSystemSensorManagerMethods[] = {
{"nativeIsDataInjectionEnabled",
"(J)Z",
- (void*)nativeIsDataInjectionEnabled},
+ (void*)nativeIsDataInjectionEnabled },
+
+ {"nativeCreateDirectChannel",
+ "(JJI[J)I",
+ (void*)nativeCreateDirectChannel },
+
+ {"nativeDestroyDirectChannel",
+ "(JI)V",
+ (void*)nativeDestroyDirectChannel },
+
+ {"nativeConfigDirectChannel",
+ "(JIII)I",
+ (void*)nativeConfigDirectChannel },
};
static const JNINativeMethod gBaseEventQueueMethods[] = {