Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 270e87f7 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

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



This eliminates the requirement that all sensors share a single file descriptor.
This, along with concurrent changes in other projects, fixes bugs b/1614524 and b/1614481

Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent fea1a459
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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);
}
+51 −21
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package android.hardware;

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 @@ public class SensorManager
        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,34 +293,62 @@ public class SensorManager
        }

        private class SensorThreadRunnable implements Runnable {
            private ParcelFileDescriptor mSensorDataFd;
            SensorThreadRunnable(ParcelFileDescriptor fd) {
                mSensorDataFd = fd;
            private Bundle mDataChannel;
            SensorThreadRunnable(Bundle dataChannel) {
                mDataChannel = dataChannel;
            }
            public void run() {
                //Log.d(TAG, "entering main sensor thread");
                final float[] values = new float[3];
                final int[] status = new int[1];
                final long timestamp[] = new long[1];
                Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);

                if (mSensorDataFd == null) {
                    Log.e(TAG, "mSensorDataFd == NULL, exiting");
            private boolean open() {
                if (mDataChannel == null) {
                    Log.e(TAG, "mDataChannel == NULL, exiting");
                    synchronized (sListeners) {
                        mThread = null;
                    }
                    return;
                    return false;
                }

                // this thread is guaranteed to be unique
                sensors_data_open(mSensorDataFd.getFileDescriptor());
                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 {
                    mSensorDataFd.close();
                        // 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);
                    }
                mSensorDataFd = null;
                }
                mDataChannel = null;
                return true;
            }

            public void run() {
                //Log.d(TAG, "entering main sensor thread");
                final float[] values = new float[3];
                final int[] status = new int[1];
                final long timestamp[] = new long[1];
                Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);

                if (!open()) {
                    return;
                }

                while (true) {
                    // wait for an event
@@ -1469,7 +1499,7 @@ public class SensorManager
    // 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);
}
+31 −6
Original line number Diff line number Diff line
@@ -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 @@ sensors_data_uninit(JNIEnv *env, jclass clazz)
}

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 @@ static JNINativeMethod gMethods[] = {
                                            (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 },
};
+3 −3
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package com.android.server;
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 @@ class SensorService extends ISensorService.Stub {
        _sensors_control_init();
    }
    
    public ParcelFileDescriptor getDataChanel() throws RemoteException {
    public Bundle getDataChannel() throws RemoteException {
        return _sensors_control_open();
    }
    
@@ -190,7 +190,7 @@ class SensorService extends ISensorService.Stub {
    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();
+60 −17
Original line number Diff line number Diff line
@@ -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 @@ static struct parcel_file_descriptor_offsets_t
    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 @@ android_init(JNIEnv *env, jclass clazz)
static jobject
android_open(JNIEnv *env, jclass clazz)
{
    int fd = sSensorDevice->open_data_source(sSensorDevice);
    native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
    if (!handle) {
        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 filedescriptor = env->NewObject(
            gFileDescriptorOffsets.mClass, 
            jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
                    gFileDescriptorOffsets.mConstructor);
    
    if (filedescriptor != NULL) {
        env->SetIntField(filedescriptor, gFileDescriptorOffsets.mDescriptor, fd);
            env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
            // new ParcelFileDescriptor()
        return env->NewObject(gParcelFileDescriptorOffsets.mClass,
                gParcelFileDescriptorOffsets.mConstructor, 
                filedescriptor);
            jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
                    gParcelFileDescriptorOffsets.mConstructor, fd);
            env->SetObjectArrayElement(fdArray, i, pfd);
        }
    close(fd);
    return NULL;
        // 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 @@ android_data_wake(JNIEnv *env, jclass clazz)

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 @@ int register_android_server_SensorService(JNIEnv *env)

    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));