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.