diff --git a/api/current.txt b/api/current.txt
index cd66ed67da02b..bf2aef2023e80 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14161,6 +14161,7 @@ package android.hardware {
public final class Sensor {
method public int getFifoMaxEventCount();
method public int getFifoReservedEventCount();
+ method public int getHighestDirectReportRateLevel();
method public int getId();
method public int getMaxDelay();
method public float getMaximumRange();
@@ -14174,6 +14175,7 @@ package android.hardware {
method public java.lang.String getVendor();
method public int getVersion();
method public boolean isAdditionalInfoSupported();
+ method public boolean isDirectChannelTypeSupported(int);
method public boolean isDynamicSensor();
method public boolean isWakeUpSensor();
field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
@@ -14251,6 +14253,17 @@ package android.hardware {
field public final int type;
}
+ public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ method public void close();
+ method public boolean isValid();
+ field public static final int RATE_FAST = 2; // 0x2
+ field public static final int RATE_NORMAL = 1; // 0x1
+ field public static final int RATE_STOP = 0; // 0x0
+ field public static final int RATE_VERY_FAST = 3; // 0x3
+ field public static final int TYPE_ASHMEM = 1; // 0x1
+ field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ }
+
public class SensorEvent {
field public int accuracy;
field public android.hardware.Sensor sensor;
@@ -14282,6 +14295,9 @@ package android.hardware {
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
method public static float getAltitude(float, float);
method public static void getAngleChange(float[], float[], float[]);
diff --git a/api/system-current.txt b/api/system-current.txt
index a3deab04eb284..ef4565306495e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -14706,6 +14706,7 @@ package android.hardware {
public final class Sensor {
method public int getFifoMaxEventCount();
method public int getFifoReservedEventCount();
+ method public int getHighestDirectReportRateLevel();
method public int getId();
method public int getMaxDelay();
method public float getMaximumRange();
@@ -14721,6 +14722,7 @@ package android.hardware {
method public int getVersion();
method public boolean isAdditionalInfoSupported();
method public boolean isDataInjectionSupported();
+ method public boolean isDirectChannelTypeSupported(int);
method public boolean isDynamicSensor();
method public boolean isWakeUpSensor();
field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
@@ -14802,6 +14804,17 @@ package android.hardware {
field public final int type;
}
+ public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ method public void close();
+ method public boolean isValid();
+ field public static final int RATE_FAST = 2; // 0x2
+ field public static final int RATE_NORMAL = 1; // 0x1
+ field public static final int RATE_STOP = 0; // 0x0
+ field public static final int RATE_VERY_FAST = 3; // 0x3
+ field public static final int TYPE_ASHMEM = 1; // 0x1
+ field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ }
+
public class SensorEvent {
field public int accuracy;
field public android.hardware.Sensor sensor;
@@ -14833,6 +14846,9 @@ package android.hardware {
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
method public static float getAltitude(float, float);
method public static void getAngleChange(float[], float[], float[]);
diff --git a/api/test-current.txt b/api/test-current.txt
index f07f3b4791118..b6b68ae388b4c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -14193,6 +14193,7 @@ package android.hardware {
public final class Sensor {
method public int getFifoMaxEventCount();
method public int getFifoReservedEventCount();
+ method public int getHighestDirectReportRateLevel();
method public int getId();
method public int getMaxDelay();
method public float getMaximumRange();
@@ -14206,6 +14207,7 @@ package android.hardware {
method public java.lang.String getVendor();
method public int getVersion();
method public boolean isAdditionalInfoSupported();
+ method public boolean isDirectChannelTypeSupported(int);
method public boolean isDynamicSensor();
method public boolean isWakeUpSensor();
field public static final int REPORTING_MODE_CONTINUOUS = 0; // 0x0
@@ -14283,6 +14285,17 @@ package android.hardware {
field public final int type;
}
+ public final class SensorDirectChannel implements java.lang.AutoCloseable {
+ method public void close();
+ method public boolean isValid();
+ field public static final int RATE_FAST = 2; // 0x2
+ field public static final int RATE_NORMAL = 1; // 0x1
+ field public static final int RATE_STOP = 0; // 0x0
+ field public static final int RATE_VERY_FAST = 3; // 0x3
+ field public static final int TYPE_ASHMEM = 1; // 0x1
+ field public static final int TYPE_HARDWARE_BUFFER = 2; // 0x2
+ }
+
public class SensorEvent {
field public int accuracy;
field public android.hardware.Sensor sensor;
@@ -14314,6 +14327,9 @@ package android.hardware {
public abstract class SensorManager {
method public boolean cancelTriggerSensor(android.hardware.TriggerEventListener, android.hardware.Sensor);
+ method public int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.os.MemoryFile);
+ method public android.hardware.SensorDirectChannel createDirectChannel(android.hardware.HardwareBuffer);
method public boolean flush(android.hardware.SensorEventListener);
method public static float getAltitude(float, float);
method public static void getAngleChange(float[], float[], float[]);
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 06ab13e9c0a5d..a8f377da26862 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -729,11 +729,11 @@ public final class Sensor {
private static final int DATA_INJECTION_MASK = 0x10;
private static final int DATA_INJECTION_SHIFT = 4;
- // MASK for dynamic sensor (sensor that added during runtime), bit 6.
+ // MASK for dynamic sensor (sensor that added during runtime), bit 5.
private static final int DYNAMIC_SENSOR_MASK = 0x20;
private static final int DYNAMIC_SENSOR_SHIFT = 5;
- // MASK for indication bit of sensor additional information support (bit 7).
+ // MASK for indication bit of sensor additional information support, bit 6.
private static final int ADDITIONAL_INFO_MASK = 0x40;
private static final int ADDITIONAL_INFO_SHIFT = 6;
@@ -796,6 +796,33 @@ public final class Sensor {
return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
}
+ /**
+ * Get the highest supported direct report mode rate level of the sensor.
+ *
+ * @return Highest direct report rate level of this sensor. If the sensor does not support
+ * direct report mode, this returns {@link SensorDirectChannel#RATE_STOP}.
+ * @see SensorDirectChannel#RATE_STOP
+ * @see SensorDirectChannel#RATE_NORMAL
+ * @see SensorDirectChannel#RATE_FAST
+ * @see SensorDirectChannel#RATE_VERY_FAST
+ */
+ @SensorDirectChannel.RateLevel
+ public int getHighestDirectReportRateLevel() {
+ return SensorDirectChannel.RATE_STOP;
+ }
+
+ /**
+ * Test if sensor support direct channel backed by a specific type of shared memory.
+ *
+ * @param sharedMemType type of shared memory used by direct channel.
+ * @return true if the shared memory type is supported.
+ * @see SensorDirectChannel#TYPE_ASHMEM
+ * @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
+ */
+ public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
+ return false;
+ }
+
static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) {
// RotationVector length has changed to 3 to 5 for API level 18
// Set it to 3 for backward compatibility.
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
new file mode 100644
index 0000000000000..fa4ab4e286689
--- /dev/null
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware;
+
+import android.annotation.IntDef;
+import android.os.MemoryFile;
+
+import dalvik.system.CloseGuard;
+
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Class representing a sensor direct channel. Use {@link
+ * SensorManager#createDirectChannel(android.os.MemoryFile)} to obtain object.
+ */
+public final class SensorDirectChannel implements AutoCloseable {
+
+ // shared memory types
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {TYPE_ASHMEM, TYPE_HARDWARE_BUFFER})
+ public @interface MemoryType {};
+ /**
+ * Shared memory type ashmem, wrapped in MemoryFile object.
+ *
+ * @see SensorManager#createDirectChannel(MemoryFile)
+ */
+ public static final int TYPE_ASHMEM = 1;
+
+ /**
+ * Shared memory type wrapped by HardwareBuffer object.
+ *
+ * @see SensorManager#createDirectChannel(HardwareBuffer)
+ */
+ public static final int TYPE_HARDWARE_BUFFER = 2;
+
+ // sensor rate levels
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, value = {RATE_STOP, RATE_NORMAL, RATE_FAST, RATE_VERY_FAST})
+ public @interface RateLevel {};
+
+ /**
+ * Sensor stopped (no event output).
+ *
+ * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public static final int RATE_STOP = 0;
+ /**
+ * Sensor operates at nominal rate of 50Hz.
+ *
+ * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 27.5Hz to
+ * 110Hz.
+ *
+ * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public static final int RATE_NORMAL = 1; //50Hz
+ /**
+ * Sensor operates at nominal rate of 200Hz.
+ *
+ * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 110Hz to
+ * 440Hz.
+ *
+ * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public static final int RATE_FAST = 2; // ~200Hz
+ /**
+ * Sensor operates at nominal rate of 800Hz.
+ *
+ * The actual rate is expected to be between 55% to 220% of nominal rate, thus between 440Hz to
+ * 1760Hz.
+ *
+ * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public static final int RATE_VERY_FAST = 3; // ~800Hz
+
+ /**
+ * Determine if a channel is still valid. A channel is invalidated after {@link #close()} is
+ * called.
+ *
+ * @return true if channel is valid.
+ */
+ public boolean isValid() {
+ return false;
+ }
+
+ /**
+ * Close sensor direct channel.
+ *
+ * Stop all active sensor in the channel and free sensor system resource related to channel.
+ * Shared memory used for creating the direct channel need to be closed or freed separately.
+ *
+ * @see SensorManager#createDirectChannel(MemoryFile)
+ * @see SensorManager#createDirectChannel(HardwareBuffer)
+ */
+ @Override
+ public void close() {
+ mCloseGuard.close();
+ if (mClosed.compareAndSet(false, true)) {
+ // actual close action
+ mManager.destroyDirectChannel(this);
+ }
+ }
+
+ /** @hide */
+ SensorDirectChannel(SensorManager manager, int id, int type, long size) {
+ mManager = manager;
+ mCloseGuard.open("SensorDirectChannel");
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ mCloseGuard.warnIfOpen();
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private final AtomicBoolean mClosed = new AtomicBoolean();
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+ private final SensorManager mManager;
+}
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 3ccac692be913..ad59b55ea2819 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -19,6 +19,7 @@ package android.hardware;
import android.annotation.SystemApi;
import android.os.Build;
import android.os.Handler;
+import android.os.MemoryFile;
import android.util.Log;
import android.util.SparseArray;
@@ -880,6 +881,92 @@ public abstract class SensorManager {
protected abstract boolean flushImpl(SensorEventListener listener);
+ /**
+ * Create a sensor direct channel backed by shared memory wrapped by MemoryFile object.
+ *
+ * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
+ * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
+ * to free up resource in sensor system associated with the direct channel.
+ *
+ * @param mem A {@link android.os.MemoryFile} shared memory object.
+ * @return A {@link android.hardware.SensorDirectChannel} object if successful, null otherwise.
+ * @throws IllegalArgumentException when mem is null.
+ * @see SensorDirectChannel#close()
+ * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public SensorDirectChannel createDirectChannel(MemoryFile mem) {
+ return null;
+ }
+
+ /**
+ * Create a sensor direct channel backed by shared memory wrapped by HardwareBuffer object.
+ *
+ * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
+ * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
+ * to free up resource in sensor system associated with the direct channel.
+ *
+ * @param mem A {@link android.hardware.HardwareBuffer} shared memory object.
+ * @return A {@link android.hardware.SensorDirectChannel} object if successful,
+ * null otherwise.
+ * @throws IllegalArgumentException when mem is null.
+ * @see SensorDirectChannel#close()
+ * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
+ */
+ public SensorDirectChannel createDirectChannel(HardwareBuffer mem) {
+ return null;
+ }
+
+ /** @hide */
+ void destroyDirectChannel(SensorDirectChannel channel) {
+ }
+
+ /**
+ * Configure sensor rate or stop sensor report on a direct report channel specified.
+ *
+ * To start event report of a sensor, or change rate of existing report, call this function with
+ * rateLevel other than {@link android.hardware.SensorDirectChannel#RATE_STOP}. Sensor events
+ * will be added into a queue formed by the shared memory used in creation of direction channel.
+ * Each element of the queue has size of 104 bytes and represents a sensor event. Data
+ * structure of an element (all fields in little-endian):
+ *
+ * offset type name
+ *- ---------------------------------------------
+ * 0x0000 int32_t size (always 104)
+ * 0x0004 int32_t sensor report token
+ * 0x0008 int32_t type (see SensorType)
+ * 0x000C uint32_t atomic counter
+ * 0x0010 int64_t timestamp (see Event)
+ * 0x0018 float[16]/int64_t[8] data (data type depends on sensor type)
+ * 0x0058 int32_t[4] reserved (set to zero)
+ *
+ * There is no head or tail pointers. The sequence and frontier of new sensor events is
+ * determined by the atomic counter, which counts from 1 after creation of direct channel and
+ * increments 1 for each new event. The writer in sensor system will wrap around from to
+ * start of shared memory region when it reaches the end. If size of memory region is not
+ * a multiple of size of element (104 bytes), the residual is not used at the end.
+ * Function returns a positive sensor report token on success. This token can be used for
+ * differentiate sensor events from multiple sensor of the same type. For example, if there are
+ * two accelerometer in the system A and B, it is guaranteed different report tokens will be
+ * returned when starting sensor A and B.
+ *
+ * To stop a sensor, call this function with rateLevel equal {@link
+ * android.hardware.SensorDirectChannel#RATE_STOP}. If the sensor parameter is left to be null,
+ * this will stop all active sensor report associated with the direct channel specified.
+ * Function return 1 on success or 0 on failure.
+ *
+ * @param channel A {@link android.hardware.SensorDirectChannel} object representing direct
+ * channel to be configured.
+ * @param sensor A {@link android.hardware.Sensor} object to denote sensor to be operated.
+ * @param rateLevel rate level defined in {@link android.hardware.SensorDirectChannel}.
+ * @return starting report or changing rate: positive sensor report token on success, 0 on failure;
+ * stopping report: 1 on success, 0 on failure.
+ * @throws IllegalArgumentException when SensorDirectChannel is null.
+ */
+ public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor,
+ @SensorDirectChannel.RateLevel int rateLevel) {
+ return 0;
+ }
+
/**
* Used for receiving notifications from the SensorManager when dynamic sensors are connected or
* disconnected.