/* * Created by LuaView. * Copyright (c) 2017, Alibaba Group. All rights reserved. * * This source code is licensed under the MIT. * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. */ package com.taobao.luaview.extend; import android.content.Context; import android.hardware.SensorEvent; import android.hardware.SensorManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.Surface; import android.view.WindowManager; import static android.hardware.SensorManager.AXIS_MINUS_X; import static android.hardware.SensorManager.AXIS_MINUS_Y; import static android.hardware.SensorManager.AXIS_X; import static android.hardware.SensorManager.AXIS_Y; public class SensorInterpreter { private static final String TAG = SensorInterpreter.class.getName(); private float[] mTiltVector = new float[3]; private boolean mTargeted = false; private float[] mTargetMatrix = new float[16]; private float[] mRotationMatrix = new float[16]; private float[] mOrientedRotationMatrix = new float[16]; private float[] mTruncatedRotationVector; private float mTiltSensitivity = 2.0f; @SuppressWarnings("SuspiciousNameCombination") public float[] interpretSensorEvent(@NonNull Context context, @Nullable SensorEvent event) { if (event == null) { return null; } float[] rotationVector = getRotationVectorFromSensorEvent(event); if (!mTargeted) { setTargetVector(rotationVector); return null; } SensorManager.getRotationMatrixFromVector(mRotationMatrix, rotationVector); final int rotation = ((WindowManager) context .getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay() .getRotation(); if (rotation == Surface.ROTATION_0) { SensorManager.getAngleChange(mTiltVector, mRotationMatrix, mTargetMatrix); } else { switch (rotation) { case Surface.ROTATION_90: SensorManager.remapCoordinateSystem(mRotationMatrix, AXIS_Y, AXIS_MINUS_X, mOrientedRotationMatrix); break; case Surface.ROTATION_180: SensorManager.remapCoordinateSystem(mRotationMatrix, AXIS_MINUS_X, AXIS_MINUS_Y, mOrientedRotationMatrix); break; case Surface.ROTATION_270: SensorManager.remapCoordinateSystem(mRotationMatrix, AXIS_MINUS_Y, AXIS_X, mOrientedRotationMatrix); break; } SensorManager.getAngleChange(mTiltVector, mOrientedRotationMatrix, mTargetMatrix); } for (int i = 0; i < mTiltVector.length; i++) { mTiltVector[i] /= Math.PI; mTiltVector[i] *= mTiltSensitivity; if (mTiltVector[i] > 1) { mTiltVector[i] = 1f; } else if (mTiltVector[i] < -1) { mTiltVector[i] = -1f; } } return mTiltVector; } @NonNull float[] getRotationVectorFromSensorEvent(@NonNull SensorEvent event) { if (event.values.length > 4) { // On some Samsung devices SensorManager.getRotationMatrixFromVector // appears to throw an exception if rotation vector has length > 4. // For the purposes of this class the first 4 values of the // rotation vector are sufficient (see crbug.com/335298 for details). if (mTruncatedRotationVector == null) { mTruncatedRotationVector = new float[4]; } System.arraycopy(event.values, 0, mTruncatedRotationVector, 0, 4); return mTruncatedRotationVector; } else { return event.values; } } protected void setTargetVector(float[] values) { SensorManager.getRotationMatrixFromVector(mTargetMatrix, values); mTargeted = true; } public void reset() { mTargeted = false; } public float getTiltSensitivity() { return mTiltSensitivity; } public void setTiltSensitivity(float tiltSensitivity) { if (tiltSensitivity <= 0) { throw new IllegalArgumentException("Tilt sensitivity must be positive"); } mTiltSensitivity = tiltSensitivity; } }