am 270e87f7: Sensors: Use a native_handle for the data channel instead of a single file descriptor.

Merge commit '270e87f71abc2edf446dbec20c725c823e8c7f37'

* commit '270e87f71abc2edf446dbec20c725c823e8c7f37':
  Sensors: Use a native_handle for the data channel instead of a single file descriptor.
diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl
index 04af2ae..67180bd 100644
--- a/core/java/android/hardware/ISensorService.aidl
+++ b/core/java/android/hardware/ISensorService.aidl
@@ -17,13 +17,13 @@
 
 package android.hardware;
 
-import android.os.ParcelFileDescriptor;
+import android.os.Bundle;
 
 /**
  * {@hide}
  */
 interface ISensorService
 {
-    ParcelFileDescriptor getDataChanel();
+    Bundle getDataChannel();
     boolean enableSensor(IBinder listener, String name, int sensor, int enable);
 }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 67df23b..bf945ec 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Looper;
+import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
@@ -280,8 +282,8 @@
         void startLocked(ISensorService service) {
             try {
                 if (mThread == null) {
-                    ParcelFileDescriptor fd = service.getDataChanel();
-                    mThread = new Thread(new SensorThreadRunnable(fd),
+                    Bundle dataChannel = service.getDataChannel();
+                    mThread = new Thread(new SensorThreadRunnable(dataChannel),
                             SensorThread.class.getName());
                     mThread.start();
                 }
@@ -291,10 +293,52 @@
         }
 
         private class SensorThreadRunnable implements Runnable {
-            private ParcelFileDescriptor mSensorDataFd;
-            SensorThreadRunnable(ParcelFileDescriptor fd) {
-                mSensorDataFd = fd;
+            private Bundle mDataChannel;
+            SensorThreadRunnable(Bundle dataChannel) {
+                mDataChannel = dataChannel;
             }
+
+            private boolean open() {
+                if (mDataChannel == null) {
+                    Log.e(TAG, "mDataChannel == NULL, exiting");
+                    synchronized (sListeners) {
+                        mThread = null;
+                    }
+                    return false;
+                }
+
+                // this thread is guaranteed to be unique
+                Parcelable[] pfds = mDataChannel.getParcelableArray("fds");
+                FileDescriptor[] fds;
+                if (pfds != null) {
+                    int length = pfds.length;
+                    fds = new FileDescriptor[length];
+                    for (int i = 0; i < length; i++) {
+                        ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
+                        fds[i] = pfd.getFileDescriptor();
+                    }
+                } else {
+                    fds = null;
+                }
+                int[] ints = mDataChannel.getIntArray("ints");
+                sensors_data_open(fds, ints);
+                if (pfds != null) {
+                    try {
+                        // close our copies of the file descriptors,
+                        // since we are just passing these to the JNI code and not using them here.
+                        for (int i = pfds.length - 1; i >= 0; i--) {
+                            ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
+                            pfd.close();
+                        }
+                    } catch (IOException e) {
+                        // *shrug*
+                        Log.e(TAG, "IOException: ", e);
+                    }
+                }
+                mDataChannel = null;
+                return true;
+            }
+
             public void run() {
                 //Log.d(TAG, "entering main sensor thread");
                 final float[] values = new float[3];
@@ -302,23 +346,9 @@
                 final long timestamp[] = new long[1];
                 Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
 
-                if (mSensorDataFd == null) {
-                    Log.e(TAG, "mSensorDataFd == NULL, exiting");
-                    synchronized (sListeners) {
-                        mThread = null;
-                    }
+                if (!open()) {
                     return;
                 }
-                // this thread is guaranteed to be unique
-                sensors_data_open(mSensorDataFd.getFileDescriptor());
-                try {
-                    mSensorDataFd.close();
-                } catch (IOException e) {
-                    // *shrug*
-                    Log.e(TAG, "IOException: ", e);
-                }
-                mSensorDataFd = null;
-
 
                 while (true) {
                     // wait for an event
@@ -1469,7 +1499,7 @@
     // Used within this module from outside SensorManager, don't make private
     static native int sensors_data_init();
     static native int sensors_data_uninit();
-    static native int sensors_data_open(FileDescriptor fd);
+    static native int sensors_data_open(FileDescriptor[] fds, int[] ints);
     static native int sensors_data_close();
     static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
 }
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 75aa458..3e27978 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Sensors"
+#define LOG_TAG "SensorManager"
+
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
 
 #include <hardware/sensors.h>
+#include <cutils/native_handle.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -106,12 +110,33 @@
 }
 
 static jint
-sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo)
+sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
 {
     jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
-    jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I");
-    int fd = env->GetIntField(fdo, offset);
-    return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd
+    jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
+    int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
+    int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
+    native_handle_t* handle = native_handle_create(numFds, numInts);
+    int offset = 0;
+
+    for (int i = 0; i < numFds; i++) {
+        jobject fdo = env->GetObjectArrayElement(fdArray, i);
+        if (fdo) {
+            handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
+        } else {
+            handle->data[offset++] = -1;
+        }
+    }
+    if (numInts > 0) {
+        jint* ints = env->GetIntArrayElements(intArray, 0);
+        for (int i = 0; i < numInts; i++) {
+            handle->data[offset++] = ints[i];
+        }
+        env->ReleaseIntArrayElements(intArray, ints, 0);
+    }
+
+    // doesn't take ownership of the native handle
+    return sSensorDevice->data_open(sSensorDevice, handle);
 }
 
 static jint
@@ -157,7 +182,7 @@
                                             (void*)sensors_module_get_next_sensor },
     {"sensors_data_init", "()I",            (void*)sensors_data_init },
     {"sensors_data_uninit", "()I",          (void*)sensors_data_uninit },
-    {"sensors_data_open",  "(Ljava/io/FileDescriptor;)I",  (void*)sensors_data_open },
+    {"sensors_data_open",  "([Ljava/io/FileDescriptor;[I)I",  (void*)sensors_data_open },
     {"sensors_data_close", "()I",           (void*)sensors_data_close },
     {"sensors_data_poll",  "([F[I[J)I",     (void*)sensors_data_poll },
 };
diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java
index b2530383f..ceef39f 100644
--- a/services/java/com/android/server/SensorService.java
+++ b/services/java/com/android/server/SensorService.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.hardware.ISensorService;
 import android.os.Binder;
-import android.os.ParcelFileDescriptor;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.util.Config;
@@ -101,7 +101,7 @@
         _sensors_control_init();
     }
     
-    public ParcelFileDescriptor getDataChanel() throws RemoteException {
+    public Bundle getDataChannel() throws RemoteException {
         return _sensors_control_open();
     }
     
@@ -190,7 +190,7 @@
     ArrayList<Listener> mListeners = new ArrayList<Listener>();
 
     private static native int _sensors_control_init();
-    private static native ParcelFileDescriptor _sensors_control_open();
+    private static native Bundle _sensors_control_open();
     private static native boolean _sensors_control_activate(int sensor, boolean activate);
     private static native int _sensors_control_set_delay(int ms);
     private static native int _sensors_control_wake();
diff --git a/services/jni/com_android_server_SensorService.cpp b/services/jni/com_android_server_SensorService.cpp
index 695a8a3..7390786 100644
--- a/services/jni/com_android_server_SensorService.cpp
+++ b/services/jni/com_android_server_SensorService.cpp
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Sensors"
+#define LOG_TAG "SensorService"
+
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
 
 #include <hardware/sensors.h>
 
@@ -36,6 +39,14 @@
     jmethodID mConstructor;
 } gParcelFileDescriptorOffsets;
 
+static struct bundle_descriptor_offsets_t
+{
+    jclass mClass;
+    jmethodID mConstructor;
+    jmethodID mPutIntArray;
+    jmethodID mPutParcelableArray;
+} gBundleOffsets;
+
 /*
  * The method below are not thread-safe and not intended to be 
  */
@@ -59,21 +70,45 @@
 static jobject
 android_open(JNIEnv *env, jclass clazz)
 {
-    int fd = sSensorDevice->open_data_source(sSensorDevice);
-    // new FileDescriptor()
-    jobject filedescriptor = env->NewObject(
-            gFileDescriptorOffsets.mClass, 
-            gFileDescriptorOffsets.mConstructor);
-    
-    if (filedescriptor != NULL) {
-        env->SetIntField(filedescriptor, gFileDescriptorOffsets.mDescriptor, fd);
-        // new ParcelFileDescriptor()
-        return env->NewObject(gParcelFileDescriptorOffsets.mClass,
-                gParcelFileDescriptorOffsets.mConstructor, 
-                filedescriptor);
+    native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
+    if (!handle) {
+        return NULL;
     }
-    close(fd);
-    return NULL;
+
+    // new Bundle()
+    jobject bundle = env->NewObject(
+            gBundleOffsets.mClass,
+            gBundleOffsets.mConstructor);
+
+    if (handle->numFds > 0) {
+        jobjectArray fdArray = env->NewObjectArray(handle->numFds,
+                gParcelFileDescriptorOffsets.mClass, NULL);
+        for (int i = 0; i < handle->numFds; i++) {
+            // new FileDescriptor()
+            jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
+                    gFileDescriptorOffsets.mConstructor);
+            env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
+            // new ParcelFileDescriptor()
+            jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
+                    gParcelFileDescriptorOffsets.mConstructor, fd);
+            env->SetObjectArrayElement(fdArray, i, pfd);
+        }
+        // bundle.putParcelableArray("fds", fdArray);
+        env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
+                env->NewStringUTF("fds"), fdArray);
+    }
+
+    if (handle->numInts > 0) {
+        jintArray intArray = env->NewIntArray(handle->numInts);
+        env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
+        // bundle.putIntArray("ints", intArray);
+        env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
+                env->NewStringUTF("ints"), intArray);
+    }
+
+    // delete the file handle, but don't close any file descriptors
+    native_handle_delete(handle);
+    return bundle;
 }
 
 static jboolean
@@ -99,7 +134,7 @@
 
 static JNINativeMethod gMethods[] = {
     {"_sensors_control_init",     "()I",   (void*) android_init },
-    {"_sensors_control_open",     "()Landroid/os/ParcelFileDescriptor;",  (void*) android_open },
+    {"_sensors_control_open",     "()Landroid/os/Bundle;",  (void*) android_open },
     {"_sensors_control_activate", "(IZ)Z", (void*) android_activate },
     {"_sensors_control_wake",     "()I", (void*) android_data_wake },
     {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },
@@ -116,7 +151,15 @@
 
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
+    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",
+            "(Ljava/io/FileDescriptor;)V");
+
+    clazz = env->FindClass("android/os/Bundle");
+    gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
+    gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
+    gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V");
+    gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray",
+            "(Ljava/lang/String;[Landroid/os/Parcelable;)V");
 
     return jniRegisterNativeMethods(env, "com/android/server/SensorService",
             gMethods, NELEM(gMethods));