125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown/*
225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * Copyright (C) 2012 The Android Open Source Project
325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *
425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * you may not use this file except in compliance with the License.
625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * You may obtain a copy of the License at
725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *
825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *
1025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * Unless required by applicable law or agreed to in writing, software
1125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * See the License for the specific language governing permissions and
1425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * limitations under the License.
1525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown */
1625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
1725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownpackage android.hardware;
1825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
1925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.os.Looper;
2025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.os.Process;
2125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.os.Handler;
2225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.os.Message;
2325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.Log;
2425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseArray;
2525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseBooleanArray;
2625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseIntArray;
2725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
2825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport java.util.ArrayList;
2925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport java.util.List;
3025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
3125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown/**
3225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * Sensor manager implementation that communicates with the built-in
3325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * system sensors.
3425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *
3525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * @hide
3625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown */
3725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownpublic class SystemSensorManager extends SensorManager {
3825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static final int SENSOR_DISABLE = -1;
3925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static boolean sSensorModuleInitialized = false;
4025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
4125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /* The thread and the sensor list are global to the process
4225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * but the actual thread is spawned on demand */
4325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static SensorThread sSensorThread;
4425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static int sQueue;
4525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
4625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    // Used within this module from outside SensorManager, don't make private
4725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
4825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static final ArrayList<ListenerDelegate> sListeners =
4925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        new ArrayList<ListenerDelegate>();
5025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
514481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    // Common pool of sensor events.
524481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    static SensorEventPool sPool;
5325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
544481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    // Looper associated with the context in which this instance was created.
554481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    final Looper mMainLooper;
5625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
5725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /*-----------------------------------------------------------------------*/
5825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
5925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static private class SensorThread {
6025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Thread mThread;
6225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean mSensorsReady;
6325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        SensorThread() {
6525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
6625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        @Override
6825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        protected void finalize() {
6925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
7025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
7125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        // must be called with sListeners lock
7225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean startLocked() {
7325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            try {
7425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (mThread == null) {
7525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mSensorsReady = false;
7625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    SensorThreadRunnable runnable = new SensorThreadRunnable();
7725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    Thread thread = new Thread(runnable, SensorThread.class.getName());
7825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    thread.start();
7925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    synchronized (runnable) {
8025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        while (mSensorsReady == false) {
8125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            runnable.wait();
8225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
8325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
8425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mThread = thread;
8525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
8625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            } catch (InterruptedException e) {
8725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
8825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mThread == null ? false : true;
8925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
9025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
9125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private class SensorThreadRunnable implements Runnable {
9225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            SensorThreadRunnable() {
9325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
9425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
9525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            private boolean open() {
9625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // NOTE: this cannot synchronize on sListeners, since
9725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // it's held in the main thread at least until we
9825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // return from here.
9925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sQueue = sensors_create_queue();
10025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                return true;
10125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
10225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
10325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            public void run() {
10425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                //Log.d(TAG, "entering main sensor thread");
10525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                final float[] values = new float[3];
10625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                final int[] status = new int[1];
10725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                final long timestamp[] = new long[1];
10825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
10925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
11025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (!open()) {
11125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    return;
11225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
11325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
11425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                synchronized (this) {
11525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // we've open the driver, we're ready to open the sensors
11625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mSensorsReady = true;
11725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    this.notify();
11825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
11925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
12025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                while (true) {
12125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // wait for an event
12225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    final int sensor = sensors_data_poll(sQueue, values, status, timestamp);
12325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
12425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    int accuracy = status[0];
12525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    synchronized (sListeners) {
12625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        if (sensor == -1 || sListeners.isEmpty()) {
12725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // we lost the connection to the event stream. this happens
12825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // when the last listener is removed or if there is an error
12925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            if (sensor == -1 && !sListeners.isEmpty()) {
13025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                // log a warning in case of abnormal termination
13125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                Log.e(TAG, "_sensors_data_poll() failed, we bail out: sensors=" + sensor);
13225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            }
13325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // we have no more listeners or polling failed, terminate the thread
13425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            sensors_destroy_queue(sQueue);
13525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            sQueue = 0;
13625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            mThread = null;
13725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            break;
13825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
13925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        final Sensor sensorObject = sHandleToSensor.get(sensor);
14025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        if (sensorObject != null) {
14125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // report the sensor event to all listeners that
14225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // care about it.
14325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            final int size = sListeners.size();
14425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            for (int i=0 ; i<size ; i++) {
14525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                ListenerDelegate listener = sListeners.get(i);
14625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                if (listener.hasSensor(sensorObject)) {
14725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                    // this is asynchronous (okay to call
14825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                    // with sListeners lock held).
14925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                    listener.onSensorChangedLocked(sensorObject,
15025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                            values, timestamp, accuracy);
15125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                }
15225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            }
15325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
15425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
15525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
15625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                //Log.d(TAG, "exiting main sensor thread");
15725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
15825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
15925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
16025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
16125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /*-----------------------------------------------------------------------*/
16225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
16325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private class ListenerDelegate {
16425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private final SensorEventListener mSensorEventListener;
16525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private final ArrayList<Sensor> mSensorList = new ArrayList<Sensor>();
16625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        private final Handler mHandler;
16725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        public SparseBooleanArray mSensors = new SparseBooleanArray();
16825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        public SparseBooleanArray mFirstEvent = new SparseBooleanArray();
16925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        public SparseIntArray mSensorAccuracies = new SparseIntArray();
17025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
17125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        ListenerDelegate(SensorEventListener listener, Sensor sensor, Handler handler) {
17225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensorEventListener = listener;
17325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
17425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // currently we create one Handler instance per listener, but we could
17525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // have one per looper (we'd need to pass the ListenerDelegate
17625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // instance to handleMessage and keep track of them separately).
17725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mHandler = new Handler(looper) {
17825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                @Override
17925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                public void handleMessage(Message msg) {
18025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    final SensorEvent t = (SensorEvent)msg.obj;
18125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    final int handle = t.sensor.getHandle();
18225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
18325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    switch (t.sensor.getType()) {
18425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // Only report accuracy for sensors that support it.
18525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        case Sensor.TYPE_MAGNETIC_FIELD:
18625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        case Sensor.TYPE_ORIENTATION:
18725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // call onAccuracyChanged() only if the value changes
18825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            final int accuracy = mSensorAccuracies.get(handle);
18925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
19025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                mSensorAccuracies.put(handle, t.accuracy);
19125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                mSensorEventListener.onAccuracyChanged(t.sensor, t.accuracy);
19225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            }
19325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            break;
19425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        default:
19525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // For other sensors, just report the accuracy once
19625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            if (mFirstEvent.get(handle) == false) {
19725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                mFirstEvent.put(handle, true);
19825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                mSensorEventListener.onAccuracyChanged(
19925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                                        t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
20025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            }
20125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            break;
20225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
20325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
20425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    mSensorEventListener.onSensorChanged(t);
20525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    sPool.returnToPool(t);
20625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
20725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            };
20825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            addSensor(sensor);
20925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
21025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
21125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        Object getListener() {
21225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mSensorEventListener;
21325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
21425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
21525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        void addSensor(Sensor sensor) {
21625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensors.put(sensor.getHandle(), true);
21725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensorList.add(sensor);
21825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
21925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        int removeSensor(Sensor sensor) {
22025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensors.delete(sensor.getHandle());
22125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mSensorList.remove(sensor);
22225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mSensors.size();
22325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
22425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean hasSensor(Sensor sensor) {
22525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mSensors.get(sensor.getHandle());
22625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
22725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        List<Sensor> getSensors() {
22825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            return mSensorList;
22925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
23025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
23125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        void onSensorChangedLocked(Sensor sensor, float[] values, long[] timestamp, int accuracy) {
23225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            SensorEvent t = sPool.getFromPool();
23325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            final float[] v = t.values;
23425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            v[0] = values[0];
23525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            v[1] = values[1];
23625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            v[2] = values[2];
23725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            t.timestamp = timestamp[0];
23825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            t.accuracy = accuracy;
23925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            t.sensor = sensor;
24025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            Message msg = Message.obtain();
24125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            msg.what = 0;
24225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            msg.obj = t;
24325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            msg.setAsynchronous(true);
24425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            mHandler.sendMessage(msg);
24525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
24625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
24725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
24825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /**
24925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     * {@hide}
25025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown     */
25125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    public SystemSensorManager(Looper mainLooper) {
25225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        mMainLooper = mainLooper;
25325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
25425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized(sListeners) {
25525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (!sSensorModuleInitialized) {
25625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sSensorModuleInitialized = true;
25725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
25825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                nativeClassInit();
25925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
26025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // initialize the sensor list
26125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sensors_module_init();
26225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                final ArrayList<Sensor> fullList = sFullSensorsList;
26325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                int i = 0;
26425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                do {
26525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    Sensor sensor = new Sensor();
26625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    i = sensors_module_get_next_sensor(sensor, i);
26725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
26825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (i>=0) {
26925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        //Log.d(TAG, "found sensor: " + sensor.getName() +
27025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        //        ", handle=" + sensor.getHandle());
27125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        fullList.add(sensor);
27225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        sHandleToSensor.append(sensor.getHandle(), sensor);
27325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
27425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                } while (i>0);
27525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
27625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sPool = new SensorEventPool( sFullSensorsList.size()*2 );
27725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sSensorThread = new SensorThread();
27825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
27925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
28025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
28125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
28225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
28325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    @Override
28425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected List<Sensor> getFullSensorList() {
28525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return sFullSensorsList;
28625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
28725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
28825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private boolean enableSensorLocked(Sensor sensor, int delay) {
28925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean result = false;
29025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        for (ListenerDelegate i : sListeners) {
29125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (i.hasSensor(sensor)) {
29225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                String name = sensor.getName();
29325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                int handle = sensor.getHandle();
29425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                result = sensors_enable_sensor(sQueue, name, handle, delay);
29525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                break;
29625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
29725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
29825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return result;
29925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
30025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
30125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private boolean disableSensorLocked(Sensor sensor) {
30225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        for (ListenerDelegate i : sListeners) {
30325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (i.hasSensor(sensor)) {
30425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // not an error, it's just that this sensor is still in use
30525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                return true;
30625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
30725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
30825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        String name = sensor.getName();
30925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        int handle = sensor.getHandle();
31025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return sensors_enable_sensor(sQueue, name, handle, SENSOR_DISABLE);
31125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
31225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
31325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
3144481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    @Override
31525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
31625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            int delay, Handler handler) {
31725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        boolean result = true;
31825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (sListeners) {
31925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // look for this listener in our list
32025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            ListenerDelegate l = null;
32125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            for (ListenerDelegate i : sListeners) {
32225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (i.getListener() == listener) {
32325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    l = i;
32425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    break;
32525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
32625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
32725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
32825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            // if we don't find it, add it to the list
32925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (l == null) {
33025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                l = new ListenerDelegate(listener, sensor, handler);
33125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sListeners.add(l);
33225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // if the list is not empty, start our main thread
33325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (!sListeners.isEmpty()) {
33425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (sSensorThread.startLocked()) {
33525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        if (!enableSensorLocked(sensor, delay)) {
33625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            // oops. there was an error
33725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            sListeners.remove(l);
33825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            result = false;
33925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
34025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    } else {
34125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // there was an error, remove the listener
34225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        sListeners.remove(l);
34325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        result = false;
34425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
34525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                } else {
34625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // weird, we couldn't add the listener
34725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    result = false;
34825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
34925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            } else if (!l.hasSensor(sensor)) {
35025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                l.addSensor(sensor);
35125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (!enableSensorLocked(sensor, delay)) {
35225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    // oops. there was an error
35325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    l.removeSensor(sensor);
35425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    result = false;
35525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
35625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
35725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
35825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
35925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return result;
36025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
36125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
36225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
36325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    @Override
36425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
36525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        synchronized (sListeners) {
36625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            final int size = sListeners.size();
36725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            for (int i=0 ; i<size ; i++) {
36825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                ListenerDelegate l = sListeners.get(i);
36925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                if (l.getListener() == listener) {
37025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (sensor == null) {
37125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        sListeners.remove(i);
37225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // disable all sensors for this listener
37325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        for (Sensor s : l.getSensors()) {
37425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                            disableSensorLocked(s);
37525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        }
37625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    } else if (l.removeSensor(sensor) == 0) {
37725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // if we have no more sensors enabled on this listener,
37825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        // take it off the list.
37925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        sListeners.remove(i);
38025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        disableSensorLocked(sensor);
38125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
38225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    break;
38325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
38425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
38525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
38625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
38725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
38825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static native void nativeClassInit();
38925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
39025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static native int sensors_module_init();
39125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static native int sensors_module_get_next_sensor(Sensor sensor, int next);
39225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
39325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    // Used within this module from outside SensorManager, don't make private
39425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static native int sensors_create_queue();
39525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static native void sensors_destroy_queue(int queue);
39625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static native boolean sensors_enable_sensor(int queue, String name, int sensor, int enable);
39725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    static native int sensors_data_poll(int queue, float[] values, int[] status, long[] timestamp);
39825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown}
399