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

Commit dc82a29b authored by Steve Block's avatar Steve Block
Browse files

Implement DeviceMotionEvent

Requires a corresponding change in external/webkit ...
https://android-git.corp.google.com/g/72906

Bug: 2495651
Change-Id: I60b2fc5a9fce459c3cef76b3b634485dfb276eae
parent b5c564fe
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 =