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

Commit 7db7c5d6 authored by Steve Block's avatar Steve Block Committed by Android (Google) Code Review
Browse files

Merge "Implement DeviceMotionEvent"

parents 78996c93 dc82a29b
Loading
Loading
Loading
Loading
+170 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.webkit;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
import android.webkit.DeviceOrientationManager;
import java.lang.Runnable;
import java.util.List;


final class DeviceMotionService implements SensorEventListener {
    private DeviceOrientationManager mManager;
    private boolean mIsRunning;
    private Handler mHandler;
    private SensorManager mSensorManager;
    private Context mContext;
    private boolean mHaveSentErrorEvent;
    private Runnable mUpdateRunnable;
    private float mLastAcceleration[];

    private static final int INTERVAL_MILLIS = 100;

    public DeviceMotionService(DeviceOrientationManager manager, Context context) {
        mManager = manager;
        assert(mManager != null);
        mContext = context;
        assert(mContext != null);
     }

    public void start() {
        mIsRunning = true;
        registerForSensor();
    }

    public void stop() {
        mIsRunning = false;
        stopSendingUpdates();
        unregisterFromSensor();
    }

    public void suspend() {
        if (mIsRunning) {
            stopSendingUpdates();
            unregisterFromSensor();
        }
    }

    public void resume() {
        if (mIsRunning) {
            registerForSensor();
        }
    }

    private void sendErrorEvent() {
        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
        // The spec requires that each listener receives the error event only once.
        if (mHaveSentErrorEvent)
            return;
        mHaveSentErrorEvent = true;
        createHandler();
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
                if (mIsRunning) {
                    // The special case of all nulls is used to signify a failure to get data.
                    mManager.onMotionChange(null, null, null, 0.0);
                }
            }
        });
    }

    private void createHandler() {
        if (mHandler != null) {
            return;
        }

        mHandler = new Handler();
        mUpdateRunnable = new Runnable() {
            @Override
            public void run() {
                mManager.onMotionChange(new Double(mLastAcceleration[0]),
                        new Double(mLastAcceleration[1]), new Double(mLastAcceleration[2]),
                        INTERVAL_MILLIS);
                mHandler.postDelayed(mUpdateRunnable, INTERVAL_MILLIS);
                // Now that we have successfully sent some data, reset whether we've sent an error.
                mHaveSentErrorEvent = false;
            }
        };
    }

    private void startSendingUpdates() {
        createHandler();
        mUpdateRunnable.run();
    }

    private void stopSendingUpdates() {
        mHandler.removeCallbacks(mUpdateRunnable);
        mLastAcceleration = null;
    }

    private void registerForSensor() {
        if (!registerForAccelerometerSensor()) {
            sendErrorEvent();
        }
    }

    private SensorManager getSensorManager() {
        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
        if (mSensorManager == null) {
            mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
        }
        return mSensorManager;
    }

    private boolean registerForAccelerometerSensor() {
        List<Sensor> sensors = getSensorManager().getSensorList(Sensor.TYPE_ACCELEROMETER);
        if (sensors.isEmpty()) {
            return false;
        }
        createHandler();
        // TODO: Consider handling multiple sensors.
        return getSensorManager().registerListener(
                this, sensors.get(0), SensorManager.SENSOR_DELAY_UI, mHandler);
    }

    private void unregisterFromSensor() {
        getSensorManager().unregisterListener(this);
    }

    /**
     * SensorEventListener implementation.
     * Callbacks happen on the thread on which we registered - the WebCore thread.
     */
    public void onSensorChanged(SensorEvent event) {
        assert(event.values.length == 3);
        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
        assert(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER);

        boolean firstData = mLastAcceleration == null;
        mLastAcceleration = event.values;
        if (firstData) {
            startSendingUpdates();
        }
    }

    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ package android.webkit;
 */
public final class DeviceOrientationManager {
    private WebViewCore mWebViewCore;
    private DeviceOrientationService mService;

    public DeviceOrientationManager(WebViewCore webViewCore) {
        mWebViewCore = webViewCore;
@@ -51,6 +50,14 @@ public final class DeviceOrientationManager {
                canProvideGamma, gamma);
    }

    // We only provide accelerationIncludingGravity.
    public void onMotionChange(Double x, Double y, Double z, double interval) {
        nativeOnMotionChange(mWebViewCore,
                x != null, x != null ? x.doubleValue() : 0.0,
                y != null, y != null ? y.doubleValue() : 0.0,
                z != null, z != null ? z.doubleValue() : 0.0,
                interval);
    }
    public void onOrientationChange(Double alpha, Double beta, Double gamma) {
        nativeOnOrientationChange(mWebViewCore,
                alpha != null, alpha != null ? alpha.doubleValue() : 0.0,
@@ -63,6 +70,9 @@ public final class DeviceOrientationManager {
    private static native void nativeSetMockOrientation(WebViewCore webViewCore,
            boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta,
            boolean canProvideGamma, double gamma);
    private static native void nativeOnMotionChange(WebViewCore webViewCore,
            boolean canProvideX, double x, boolean canProvideY, double y,
            boolean canProvideZ, double z, double interval);
    private static native void nativeOnOrientationChange(WebViewCore webViewCore,
            boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta,
            boolean canProvideGamma, double gamma);
+10 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.util.SparseBooleanArray;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.View;
import android.webkit.DeviceMotionService;
import android.webkit.DeviceOrientationManager;
import android.webkit.DeviceOrientationService;

@@ -120,6 +121,7 @@ final class WebViewCore {
    private int mWebkitScrollY = 0;

    private DeviceOrientationManager mDeviceOrientationManager = new DeviceOrientationManager(this);
    private DeviceMotionService mDeviceMotionService;
    private DeviceOrientationService mDeviceOrientationService;

    // The thread name used to identify the WebCore thread and for use in
@@ -2553,6 +2555,14 @@ final class WebViewCore {
                canProvideGamma, gamma);
    }

    protected DeviceMotionService getDeviceMotionService() {
        if (mDeviceMotionService == null) {
            mDeviceMotionService =
                    new DeviceMotionService(mDeviceOrientationManager, mContext);
        }
        return mDeviceMotionService;
    }

    protected DeviceOrientationService getDeviceOrientationService() {
        if (mDeviceOrientationService == null) {
            mDeviceOrientationService =