Merge changes from topic 'sensor_direct_report'
* changes: Sensor event direct report mode implementation Sensor event direct report mode support API
This commit is contained in:
committed by
Android (Google) Code Review
commit
b81d978490
@@ -14208,6 +14208,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();
|
||||
@@ -14221,6 +14222,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
|
||||
@@ -14298,6 +14300,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;
|
||||
@@ -14329,6 +14342,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[]);
|
||||
|
||||
@@ -14766,6 +14766,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();
|
||||
@@ -14781,6 +14782,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
|
||||
@@ -14862,6 +14864,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;
|
||||
@@ -14893,6 +14906,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[]);
|
||||
|
||||
@@ -14240,6 +14240,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();
|
||||
@@ -14253,6 +14254,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
|
||||
@@ -14330,6 +14332,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;
|
||||
@@ -14361,6 +14374,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[]);
|
||||
|
||||
@@ -729,14 +729,22 @@ 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;
|
||||
|
||||
// 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.
|
||||
@@ -796,6 +804,42 @@ 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() {
|
||||
int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
|
||||
return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
|
||||
? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <code>true</code> if the shared memory type is supported.
|
||||
* @see SensorDirectChannel#TYPE_ASHMEM
|
||||
* @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
|
||||
// Set it to 3 for backward compatibility.
|
||||
|
||||
168
core/java/android/hardware/SensorDirectChannel.java
Normal file
168
core/java/android/hardware/SensorDirectChannel.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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 <code>true</code> if channel is valid.
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return !mClosed.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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 {
|
||||
mCloseGuard.warnIfOpen();
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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,104 @@ 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 createDirectChannelImpl(mem.length(), mem, 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 */
|
||||
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.
|
||||
*
|
||||
* 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 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
@@ -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[] = {
|
||||
|
||||
Reference in New Issue
Block a user