Merge "Address review suggestions for sensor direct report related APIs" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index d5f9512..5734aed 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14858,15 +14858,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     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
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -14900,7 +14901,6 @@
 
   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);
diff --git a/api/removed.txt b/api/removed.txt
index d20c08c..82705fd 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -100,6 +100,18 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3066a44..1f059f4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -15631,15 +15631,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     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
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -15673,7 +15674,6 @@
 
   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);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 1effe9c..bdcafae 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -98,6 +98,18 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 21221cc..e144382 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -14903,15 +14903,16 @@
     field public final int type;
   }
 
-  public final class SensorDirectChannel implements java.lang.AutoCloseable {
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
     method public void close();
-    method public boolean isValid();
+    method public int configure(android.hardware.Sensor, int);
+    method public boolean isOpen();
     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
+    field public static final int TYPE_MEMORY_FILE = 1; // 0x1
   }
 
   public class SensorEvent {
@@ -14945,7 +14946,6 @@
 
   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);
diff --git a/api/test-removed.txt b/api/test-removed.txt
index d20c08c..82705fd 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -100,6 +100,18 @@
 
 }
 
+package android.hardware {
+
+  public final class SensorDirectChannel implements java.nio.channels.Channel {
+    method public deprecated boolean isValid();
+  }
+
+  public abstract class SensorManager {
+    method public deprecated int configureDirectChannel(android.hardware.SensorDirectChannel, android.hardware.Sensor, int);
+  }
+
+}
+
 package android.media {
 
   public final class AudioFormat implements android.os.Parcelable {
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 0218cb5..a895f82 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -836,16 +836,16 @@
     }
 
     /**
-     * Test if sensor support direct channel backed by a specific type of shared memory.
+     * Test if a sensor supports a specified direct channel type.
      *
      * @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
+     * @return <code>true</code> if the specified shared memory type is supported.
+     * @see SensorDirectChannel#TYPE_MEMORY_FILE
      * @see SensorDirectChannel#TYPE_HARDWARE_BUFFER
      */
     public boolean isDirectChannelTypeSupported(@SensorDirectChannel.MemoryType int sharedMemType) {
         switch (sharedMemType) {
-            case SensorDirectChannel.TYPE_ASHMEM:
+            case SensorDirectChannel.TYPE_MEMORY_FILE:
                 return (mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0;
             case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
                 return (mFlags & (1 << DIRECT_CHANNEL_SHIFT + 1)) > 0;
diff --git a/core/java/android/hardware/SensorDirectChannel.java b/core/java/android/hardware/SensorDirectChannel.java
index a65d57d..bd7f9cf 100644
--- a/core/java/android/hardware/SensorDirectChannel.java
+++ b/core/java/android/hardware/SensorDirectChannel.java
@@ -23,26 +23,31 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.channels.Channel;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * Class representing a sensor direct channel. Use {@link
- * SensorManager#createDirectChannel(android.os.MemoryFile)} to obtain object.
+ * Class representing a sensor direct channel. Use
+ * {@link SensorManager#createDirectChannel(android.os.MemoryFile)} or
+ * {@link SensorManager#createDirectChannel(android.hardware.HardwareBuffer)}
+ * to obtain an object. The channel object can be then configured
+ * (see {@link #configure(Sensor, int)})
+ * to start delivery of sensor events into shared memory buffer.
  */
-public final class SensorDirectChannel implements AutoCloseable {
+public final class SensorDirectChannel implements Channel {
 
     // shared memory types
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(flag = true, value = {TYPE_ASHMEM, TYPE_HARDWARE_BUFFER})
+    @IntDef(flag = true, value = {TYPE_MEMORY_FILE, 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;
+    public static final int TYPE_MEMORY_FILE = 1;
 
     /**
      * Shared memory type wrapped by HardwareBuffer object.
@@ -61,7 +66,7 @@
     /**
      * Sensor stopped (no event output).
      *
-     * @see SensorManager#configureDirectChannel(SensorDirectChannel, Sensor, int)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_STOP = 0;
     /**
@@ -70,7 +75,7 @@
      * 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)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_NORMAL = 1; //50Hz
     /**
@@ -79,7 +84,7 @@
      * 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)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_FAST = 2; // ~200Hz
     /**
@@ -88,7 +93,7 @@
      * 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)
+     * @see #configure(Sensor, int)
      */
     public static final int RATE_VERY_FAST = 3; // ~800Hz
 
@@ -98,10 +103,17 @@
      *
      * @return <code>true</code> if channel is valid.
      */
-    public boolean isValid() {
+    @Override
+    public boolean isOpen() {
         return !mClosed.get();
     }
 
+    /** @removed */
+    @Deprecated
+    public boolean isValid() {
+        return isOpen();
+    }
+
     /**
      * Close sensor direct channel.
      *
@@ -113,13 +125,61 @@
      */
     @Override
     public void close() {
-        mCloseGuard.close();
         if (mClosed.compareAndSet(false, true)) {
+            mCloseGuard.close();
             // actual close action
             mManager.destroyDirectChannel(this);
         }
     }
 
+    /**
+     * Configure sensor rate or stop sensor report.
+     *
+     * 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):
+     *
+     * <pre>
+     *   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)
+     * </pre>
+     *
+     * There are 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. Atomic counter will wrap back to 1 after it reaches
+     * UINT32_MAX, skipping value 0 to avoid confusion with uninitialized memory. The writer in
+     * sensor system will wrap around from the 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 to differentiate sensor events from multiple sensor of the same type. For
+     * example, if there are two accelerometers 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 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 NullPointerException when channel is null.
+     */
+    public int configure(Sensor sensor, @RateLevel int rateLevel) {
+        return mManager.configureDirectChannelImpl(this, sensor, rateLevel);
+    }
+
     /** @hide */
     SensorDirectChannel(SensorManager manager, int id, int type, long size) {
         mManager = manager;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 1dc6478..ed56391 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -882,7 +882,12 @@
 
 
     /**
-     * Create a sensor direct channel backed by shared memory wrapped by MemoryFile object.
+     * Create a sensor direct channel backed by shared memory wrapped in MemoryFile object.
+     *
+     * The resulting channel can be used for delivering sensor events to native code, other
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+     * and cares about sensor event latency.
      *
      * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
      * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -890,7 +895,7 @@
      *
      * @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.
+     * @throws NullPointerException when mem is null.
      * @see SensorDirectChannel#close()
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
@@ -899,7 +904,12 @@
     }
 
     /**
-     * Create a sensor direct channel backed by shared memory wrapped by HardwareBuffer object.
+     * Create a sensor direct channel backed by shared memory wrapped in HardwareBuffer object.
+     *
+     * The resulting channel can be used for delivering sensor events to native code, other
+     * processes, GPU/DSP or other co-processors without CPU intervention. This is the recommanded
+     * for high performance sensor applications that use high sensor rates (e.g. greater than 200Hz)
+     * and cares about sensor event latency.
      *
      * Use the returned {@link android.hardware.SensorDirectChannel} object to configure direct
      * report of sensor events. After use, call {@link android.hardware.SensorDirectChannel#close()}
@@ -908,7 +918,7 @@
      * @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.
+     * @throws NullPointerException when mem is null.
      * @see SensorDirectChannel#close()
      * @see #configureDirectChannel(SensorDirectChannel, Sensor, int)
      */
@@ -928,50 +938,9 @@
     /** @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) {
+    /** @removed */
+    @Deprecated
+    public int configureDirectChannel(SensorDirectChannel channel, Sensor sensor, int rateLevel) {
         return configureDirectChannelImpl(channel, sensor, rateLevel);
     }
 
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 0677179..10c4cb3 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -35,6 +35,7 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -500,10 +501,8 @@
     /** @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 (!channel.isOpen()) {
+            throw new IllegalStateException("channel is closed");
         }
 
         if (rate < SensorDirectChannel.RATE_STOP
@@ -532,7 +531,8 @@
     /** @hide */
     protected SensorDirectChannel createDirectChannelImpl(
             MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
-        SensorDirectChannel ch = null;
+        int id;
+        int type;
         long size;
         if (memoryFile != null) {
             int fd;
@@ -549,11 +549,13 @@
             }
 
             size = memoryFile.length();
-            int id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_ASHMEM, fd, null);
-            if (id > 0) {
-                ch = new SensorDirectChannel(this, id, SensorDirectChannel.TYPE_ASHMEM, size);
+            id = nativeCreateDirectChannel(
+                    mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+            if (id <= 0) {
+                throw new UncheckedIOException(
+                        new IOException("create MemoryFile direct channel failed " + id));
             }
+            type = SensorDirectChannel.TYPE_MEMORY_FILE;
         } else if (hardwareBuffer != null) {
             if (hardwareBuffer.getFormat() != HardwareBuffer.BLOB) {
                 throw new IllegalArgumentException("Format of HardwareBuffer must be BLOB");
@@ -571,18 +573,18 @@
                         "HardwareBuffer must set usage flag USAGE0_SENSOR_DIRECT_DATA");
             }
             size = hardwareBuffer.getWidth();
-            int id = nativeCreateDirectChannel(
+            id = nativeCreateDirectChannel(
                     mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
                     -1, hardwareBuffer);
-            if (id > 0) {
-                ch = new SensorDirectChannel(
-                        this, id, SensorDirectChannel.TYPE_HARDWARE_BUFFER, size);
+            if (id <= 0) {
+                throw new UncheckedIOException(
+                        new IOException("create HardwareBuffer direct channel failed " + id));
             }
+            type = SensorDirectChannel.TYPE_HARDWARE_BUFFER;
         } else {
-            throw new IllegalArgumentException("Invalid parameter");
+            throw new NullPointerException("shared memory object cannot be null");
         }
-
-        return ch;
+        return new SensorDirectChannel(this, id, type, size);
     }
 
     /** @hide */