16d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh    /*
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
196d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganeshimport android.content.Context;
2025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.os.Handler;
21db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianimport android.os.Looper;
22db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianimport android.os.MessageQueue;
232e90089766c047687662d402819018b308e83d15Jaikumar Ganeshimport android.util.Log;
2425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseArray;
2525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseBooleanArray;
2625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownimport android.util.SparseIntArray;
279a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganeshimport dalvik.system.CloseGuard;
289a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
299a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganeshimport java.util.ArrayList;
309a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganeshimport java.util.HashMap;
319a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganeshimport java.util.List;
3225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
3325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown/**
3425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * Sensor manager implementation that communicates with the built-in
3525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * system sensors.
3625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown *
3725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown * @hide
3825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown */
3925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brownpublic class SystemSensorManager extends SensorManager {
40db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private static native void nativeClassInit();
41db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private static native int nativeGetNextSensor(Sensor sensor, int next);
42db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
4325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    private static boolean sSensorModuleInitialized = false;
44db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private static final Object sSensorModuleLock = new Object();
45db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private static final ArrayList<Sensor> sFullSensorsList = new ArrayList<Sensor>();
46db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private static final SparseArray<Sensor> sHandleToSensor = new SparseArray<Sensor>();
4725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
48db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    // Listener list
499a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    private final HashMap<SensorEventListener, SensorEventQueue> mSensorListeners =
509a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            new HashMap<SensorEventListener, SensorEventQueue>();
519a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    private final HashMap<TriggerEventListener, TriggerEventQueue> mTriggerListeners =
529a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            new HashMap<TriggerEventListener, TriggerEventQueue>();
5325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
544481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    // Looper associated with the context in which this instance was created.
55db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    private final Looper mMainLooper;
566d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh    private final int mTargetSdkLevel;
5725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
58db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    /** {@hide} */
596d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh    public SystemSensorManager(Context context, Looper mainLooper) {
6025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        mMainLooper = mainLooper;
616d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        mTargetSdkLevel = context.getApplicationInfo().targetSdkVersion;
62db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        synchronized(sSensorModuleLock) {
6325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            if (!sSensorModuleInitialized) {
6425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                sSensorModuleInitialized = true;
6525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                nativeClassInit();
6725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
6825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                // initialize the sensor list
6925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                final ArrayList<Sensor> fullList = sFullSensorsList;
7025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                int i = 0;
7125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                do {
7225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    Sensor sensor = new Sensor();
73db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    i = nativeGetNextSensor(sensor, i);
7425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    if (i>=0) {
7525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        //Log.d(TAG, "found sensor: " + sensor.getName() +
7625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        //        ", handle=" + sensor.getHandle());
7725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        fullList.add(sensor);
7825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                        sHandleToSensor.append(sensor.getHandle(), sensor);
7925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
8025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                } while (i>0);
8125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
8225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
8325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
8425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
85db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
8625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
8725157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    @Override
8825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    protected List<Sensor> getFullSensorList() {
8925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        return sFullSensorsList;
9025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
9125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
92db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
93db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    /** @hide */
94db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    @Override
95db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
964bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
974bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        if (listener == null || sensor == null) {
984bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            Log.e(TAG, "sensor or listener is null");
994bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            return false;
1004bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        }
101b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        // Trigger Sensors should use the requestTriggerSensor call.
1024bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        if (Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) {
1034bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            Log.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
1044bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            return false;
1054bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        }
1064bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
1074bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            Log.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
1084bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            return false;
1094bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        }
110b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
111db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        // Invariants to preserve:
112db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        // - one Looper per SensorEventListener
113db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        // - one Looper per SensorEventQueue
1149a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        // We map SensorEventListener to a SensorEventQueue, which holds the looper
1159a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        synchronized (mSensorListeners) {
1169a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            SensorEventQueue queue = mSensorListeners.get(listener);
1179a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            if (queue == null) {
118db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;
1194bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                queue = new SensorEventQueue(listener, looper, this);
120b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags)) {
121db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    queue.dispose();
1229a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    return false;
123db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                }
1249a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                mSensorListeners.put(listener, queue);
1259a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                return true;
1269a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            } else {
127b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags);
12825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
12925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
13025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
13125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
13225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    /** @hide */
1334481d9c10ceaf3b886fb5cab1d20941932af5b0fJeff Brown    @Override
134db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
1359a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        // Trigger Sensors should use the cancelTriggerSensor call.
1369a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        if (sensor != null && Sensor.getReportingMode(sensor) == Sensor.REPORTING_MODE_ONE_SHOT) {
1379a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            return;
1389a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        }
13925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
1409a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        synchronized (mSensorListeners) {
1419a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            SensorEventQueue queue = mSensorListeners.get(listener);
142db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (queue != null) {
1439a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                boolean result;
1449a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                if (sensor == null) {
1459a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    result = queue.removeAllSensors();
14625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                } else {
1472e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                    result = queue.removeSensor(sensor, true);
14825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
1499a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                if (result && !queue.hasSensors()) {
1509a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    mSensorListeners.remove(listener);
151db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    queue.dispose();
15225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
15325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
15425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
155db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    }
15625157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
1579a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /** @hide */
1589a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    @Override
1599a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
1609a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        if (sensor == null) throw new IllegalArgumentException("sensor cannot be null");
1619a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
1629a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        if (Sensor.getReportingMode(sensor) != Sensor.REPORTING_MODE_ONE_SHOT) return false;
163db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
1649a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        synchronized (mTriggerListeners) {
1659a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            TriggerEventQueue queue = mTriggerListeners.get(listener);
1669a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            if (queue == null) {
1679a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                queue = new TriggerEventQueue(listener, mMainLooper, this);
168b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                if (!queue.addSensor(sensor, 0, 0, 0)) {
1699a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    queue.dispose();
1709a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    return false;
1719a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                }
1729a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                mTriggerListeners.put(listener, queue);
1739a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                return true;
1741aab1dbca5cf7386797ce609c768249247233186Jaikumar Ganesh            } else {
175b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                return queue.addSensor(sensor, 0, 0, 0);
1769a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            }
1779a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        }
1789a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    }
1799a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
1809a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    /** @hide */
1819a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    @Override
1822e90089766c047687662d402819018b308e83d15Jaikumar Ganesh    protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
1832e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            boolean disable) {
1849a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        if (sensor != null && Sensor.getReportingMode(sensor) != Sensor.REPORTING_MODE_ONE_SHOT) {
1859a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            return false;
1869a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        }
1879a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        synchronized (mTriggerListeners) {
1889a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            TriggerEventQueue queue = mTriggerListeners.get(listener);
1899a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            if (queue != null) {
1909a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                boolean result;
1919a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                if (sensor == null) {
1929a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    result = queue.removeAllSensors();
1939a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                } else {
1942e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                    result = queue.removeSensor(sensor, disable);
1959a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                }
1969a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                if (result && !queue.hasSensors()) {
1979a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    mTriggerListeners.remove(listener);
1989a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                    queue.dispose();
1999a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                }
2009a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                return result;
201db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
2029a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            return false;
203db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
20425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
20525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
2064bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella    protected boolean flushImpl(SensorEventListener listener) {
2074bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        if (listener == null) throw new IllegalArgumentException("listener cannot be null");
208b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
2094bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        synchronized (mSensorListeners) {
2104bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            SensorEventQueue queue = mSensorListeners.get(listener);
2114bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            if (queue == null) {
2124bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                return false;
2134bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            } else {
2144bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                return (queue.flush() == 0);
2154bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            }
216b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        }
217b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
218b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
219db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    /*
2209a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * BaseEventQueue is the communication channel with the sensor service,
2219a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * SensorEventQueue, TriggerEventQueue are subclases and there is one-to-one mapping between
2229a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh     * the queues and the listeners.
223db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian     */
2249a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    private static abstract class BaseEventQueue {
2259a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        private native int nativeInitBaseEventQueue(BaseEventQueue eventQ, MessageQueue msgQ,
2269a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                float[] scratch);
227b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        private static native int nativeEnableSensor(int eventQ, int handle, int rateUs,
228b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                int maxBatchReportLatencyUs, int reservedFlags);
229db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private static native int nativeDisableSensor(int eventQ, int handle);
230db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private static native void nativeDestroySensorEventQueue(int eventQ);
2314bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        private static native int nativeFlushSensor(int eventQ);
232db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private int nSensorEventQueue;
233db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private final SparseBooleanArray mActiveSensors = new SparseBooleanArray();
2349a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        protected final SparseIntArray mSensorAccuracies = new SparseIntArray();
2359a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        protected final SparseBooleanArray mFirstEvent = new SparseBooleanArray();
236db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private final CloseGuard mCloseGuard = CloseGuard.get();
237db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private final float[] mScratch = new float[16];
2386d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        protected final SystemSensorManager mManager;
239db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
2406d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        BaseEventQueue(Looper looper, SystemSensorManager manager) {
2419a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            nSensorEventQueue = nativeInitBaseEventQueue(this, looper.getQueue(), mScratch);
242db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            mCloseGuard.open("dispose");
2436d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            mManager = manager;
244db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
2459a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
246db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        public void dispose() {
247db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            dispose(false);
248db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
249db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
250b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        public boolean addSensor(
251b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                Sensor sensor, int delayUs, int maxBatchReportLatencyUs, int reservedFlags) {
2529a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            // Check if already present.
2532e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            int handle = sensor.getHandle();
2542e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            if (mActiveSensors.get(handle)) return false;
2552e90089766c047687662d402819018b308e83d15Jaikumar Ganesh
2562e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            // Get ready to receive events before calling enable.
2572e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            mActiveSensors.put(handle, true);
2582e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            addSensorEvent(sensor);
259b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs, reservedFlags) != 0) {
260b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                // Try continuous mode if batching fails.
261b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                if (maxBatchReportLatencyUs == 0 ||
262b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                    maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0, 0) != 0) {
263b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                  removeSensor(sensor, false);
264b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                  return false;
265b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                }
266db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
2672e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            return true;
268db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
269db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
2709a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        public boolean removeAllSensors() {
271db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            for (int i=0 ; i<mActiveSensors.size(); i++) {
272db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                if (mActiveSensors.valueAt(i) == true) {
273db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    int handle = mActiveSensors.keyAt(i);
274db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    Sensor sensor = sHandleToSensor.get(handle);
275db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    if (sensor != null) {
276db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                        disableSensor(sensor);
277db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                        mActiveSensors.put(handle, false);
2786d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                        removeSensorEvent(sensor);
279db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    } else {
280db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                        // it should never happen -- just ignore.
28125157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                    }
28225157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown                }
28325157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown            }
2849a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            return true;
28525157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown        }
286db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
2872e90089766c047687662d402819018b308e83d15Jaikumar Ganesh        public boolean removeSensor(Sensor sensor, boolean disable) {
288db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            final int handle = sensor.getHandle();
289db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (mActiveSensors.get(handle)) {
2902e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                if (disable) disableSensor(sensor);
291db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                mActiveSensors.put(sensor.getHandle(), false);
2926d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                removeSensorEvent(sensor);
2939a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                return true;
294db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
2959a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            return false;
296db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
297db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
2984bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella        public int flush() {
299b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            if (nSensorEventQueue == 0) throw new NullPointerException();
3004bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            return nativeFlushSensor(nSensorEventQueue);
301b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        }
302b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
303db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        public boolean hasSensors() {
304db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            // no more sensors are set
305db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            return mActiveSensors.indexOfValue(true) >= 0;
306db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
3079a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
308db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        @Override
309db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        protected void finalize() throws Throwable {
310db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            try {
311db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                dispose(true);
312db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            } finally {
313db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                super.finalize();
314db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
315db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
316db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
317db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private void dispose(boolean finalized) {
318db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (mCloseGuard != null) {
319db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                if (finalized) {
320db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    mCloseGuard.warnIfOpen();
321db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                }
322db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                mCloseGuard.close();
323db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
324db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (nSensorEventQueue != 0) {
325db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                nativeDestroySensorEventQueue(nSensorEventQueue);
326db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                nSensorEventQueue = 0;
327db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
328db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
329db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
330b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        private int enableSensor(
331b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                Sensor sensor, int rateUs, int maxBatchReportLatencyUs, int reservedFlags) {
332db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (nSensorEventQueue == 0) throw new NullPointerException();
333db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (sensor == null) throw new NullPointerException();
334b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs,
335b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                    maxBatchReportLatencyUs, reservedFlags);
336db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
337b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
338db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        private int disableSensor(Sensor sensor) {
339db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (nSensorEventQueue == 0) throw new NullPointerException();
340db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            if (sensor == null) throw new NullPointerException();
341db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            return nativeDisableSensor(nSensorEventQueue, sensor.getHandle());
342db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
3439a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy,
3449a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                long timestamp);
345b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        protected abstract void dispatchFlushCompleteEvent(int handle);
3466d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh
3476d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        protected abstract void addSensorEvent(Sensor sensor);
3486d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        protected abstract void removeSensorEvent(Sensor sensor);
3499a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    }
3509a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
3519a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    static final class SensorEventQueue extends BaseEventQueue {
3529a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        private final SensorEventListener mListener;
3536d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();
3549a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
3556d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        public SensorEventQueue(SensorEventListener listener, Looper looper,
3564bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                SystemSensorManager manager) {
3576d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            super(looper, manager);
3589a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            mListener = listener;
3599a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        }
360db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
36131d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella        @Override
3626d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        public void addSensorEvent(Sensor sensor) {
3636d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,
3646d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    mManager.mTargetSdkLevel));
36531d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mSensorsEvents) {
36631d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                mSensorsEvents.put(sensor.getHandle(), t);
36731d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
3686d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        }
3696d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh
37031d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella        @Override
3716d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        public void removeSensorEvent(Sensor sensor) {
37231d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mSensorsEvents) {
37331d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                mSensorsEvents.delete(sensor.getHandle());
37431d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
3756d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        }
3766d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh
377db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        // Called from native code.
378db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        @SuppressWarnings("unused")
3799a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        @Override
3809a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,
3819a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh                long timestamp) {
3829a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            final Sensor sensor = sHandleToSensor.get(handle);
38331d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            SensorEvent t = null;
38431d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mSensorsEvents) {
38531d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                t = mSensorsEvents.get(handle);
38631d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
38731d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella
3882e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            if (t == null) {
38931d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                // This may happen if the client has unregistered and there are pending events in
39031d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                // the queue waiting to be delivered. Ignore.
3912e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                return;
3922e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            }
3936d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            // Copy from the values array.
3946d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            System.arraycopy(values, 0, t.values, 0, t.values.length);
3956d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            t.timestamp = timestamp;
3966d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            t.accuracy = inAccuracy;
3976d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            t.sensor = sensor;
3986d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            switch (t.sensor.getType()) {
3996d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                // Only report accuracy for sensors that support it.
4006d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                case Sensor.TYPE_MAGNETIC_FIELD:
4016d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                case Sensor.TYPE_ORIENTATION:
4026d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    // call onAccuracyChanged() only if the value changes
4036d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    final int accuracy = mSensorAccuracies.get(handle);
4046d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    if ((t.accuracy >= 0) && (accuracy != t.accuracy)) {
4056d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                        mSensorAccuracies.put(handle, t.accuracy);
4066d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                        mListener.onAccuracyChanged(t.sensor, t.accuracy);
4076d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    }
4086d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    break;
4096d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                default:
4106d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    // For other sensors, just report the accuracy once
4116d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    if (mFirstEvent.get(handle) == false) {
4126d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                        mFirstEvent.put(handle, true);
4136d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                        mListener.onAccuracyChanged(
4146d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                                t.sensor, SENSOR_STATUS_ACCURACY_HIGH);
4156d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    }
4166d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    break;
417db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
4186d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            mListener.onSensorChanged(t);
419db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
420b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
421b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        @SuppressWarnings("unused")
422b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        protected void dispatchFlushCompleteEvent(int handle) {
4234bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella            if (mListener instanceof SensorEventListener2) {
4244bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                final Sensor sensor = sHandleToSensor.get(handle);
4254bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella                ((SensorEventListener2)mListener).onFlushCompleted(sensor);
426b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            }
427b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            return;
428b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        }
42925157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown    }
43025157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
4319a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    static final class TriggerEventQueue extends BaseEventQueue {
4329a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        private final TriggerEventListener mListener;
4336d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        private final SparseArray<TriggerEvent> mTriggerEvents = new SparseArray<TriggerEvent>();
43425157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown
4359a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        public TriggerEventQueue(TriggerEventListener listener, Looper looper,
4366d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                SystemSensorManager manager) {
4376d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            super(looper, manager);
4389a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            mListener = listener;
4396d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        }
4406d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh
44131d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella        @Override
4426d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        public void addSensorEvent(Sensor sensor) {
4436d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            TriggerEvent t = new TriggerEvent(Sensor.getMaxLengthValuesArray(sensor,
4446d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                    mManager.mTargetSdkLevel));
44531d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mTriggerEvents) {
44631d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                mTriggerEvents.put(sensor.getHandle(), t);
44731d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
4486d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        }
4496d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh
45031d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella        @Override
4516d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        public void removeSensorEvent(Sensor sensor) {
45231d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mTriggerEvents) {
45331d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                mTriggerEvents.delete(sensor.getHandle());
45431d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
4551aab1dbca5cf7386797ce609c768249247233186Jaikumar Ganesh        }
456bc03a348d78326dee779a8ecc325799c9fceac98Jaikumar Ganesh
4579a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        // Called from native code.
4589a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        @SuppressWarnings("unused")
4599a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh        @Override
4606d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh        protected void dispatchSensorEvent(int handle, float[] values, int accuracy,
4616d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh                long timestamp) {
4629a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            final Sensor sensor = sHandleToSensor.get(handle);
46331d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            TriggerEvent t = null;
46431d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            synchronized (mTriggerEvents) {
46531d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella                t = mTriggerEvents.get(handle);
46631d14ce57ca230588d8ffe991ee827b12d8ed17eAravind Akella            }
4672e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            if (t == null) {
4682e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                Log.e(TAG, "Error: Trigger Event is null for Sensor: " + sensor);
4692e90089766c047687662d402819018b308e83d15Jaikumar Ganesh                return;
4702e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            }
471bc03a348d78326dee779a8ecc325799c9fceac98Jaikumar Ganesh
4726d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            // Copy from the values array.
4736d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            System.arraycopy(values, 0, t.values, 0, t.values.length);
4746d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            t.timestamp = timestamp;
4756d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            t.sensor = sensor;
4769a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
4772e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            // A trigger sensor is auto disabled. So just clean up and don't call native
4782e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            // disable.
4792e90089766c047687662d402819018b308e83d15Jaikumar Ganesh            mManager.cancelTriggerSensorImpl(mListener, sensor, false);
4809a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh
4816d0c1d78f121d4f1b72973740e8b120c7def1dc0Jaikumar Ganesh            mListener.onTrigger(t);
482db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
483b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
484b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        @SuppressWarnings("unused")
485b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        protected void dispatchFlushCompleteEvent(int handle) {
486b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella        }
487b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    }
48825157e458d6e10b027d1ba6b78b0487156c9f57aJeff Brown}
489