blob: 92e62b098bde991c7accc60ab076c80acd9ee068 [file] [log] [blame]
Eric Erfanianccca3152017-02-22 16:32:36 -08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.incallui;
18
19import android.content.Context;
20import android.hardware.Sensor;
21import android.hardware.SensorEvent;
22import android.hardware.SensorEventListener;
23import android.hardware.SensorManager;
24import android.os.Handler;
25import android.os.Message;
linyuh183cb712017-12-27 17:02:37 -080026import com.android.dialer.common.LogUtil;
Eric Erfanianccca3152017-02-22 16:32:36 -080027
28/**
29 * This class is used to listen to the accelerometer to monitor the orientation of the phone. The
30 * client of this class is notified when the orientation changes between horizontal and vertical.
31 */
32public class AccelerometerListener {
33
34 // Device orientation
35 public static final int ORIENTATION_UNKNOWN = 0;
36 public static final int ORIENTATION_VERTICAL = 1;
37 public static final int ORIENTATION_HORIZONTAL = 2;
38 private static final String TAG = "AccelerometerListener";
39 private static final boolean DEBUG = true;
40 private static final boolean VDEBUG = false;
41 private static final int ORIENTATION_CHANGED = 1234;
42 private static final int VERTICAL_DEBOUNCE = 100;
43 private static final int HORIZONTAL_DEBOUNCE = 500;
44 private static final double VERTICAL_ANGLE = 50.0;
linyuh183cb712017-12-27 17:02:37 -080045 private SensorManager sensorManager;
46 private Sensor sensor;
Eric Erfanianccca3152017-02-22 16:32:36 -080047 // mOrientation is the orientation value most recently reported to the client.
linyuh183cb712017-12-27 17:02:37 -080048 private int orientation;
Eric Erfanianccca3152017-02-22 16:32:36 -080049 // mPendingOrientation is the latest orientation computed based on the sensor value.
50 // This is sent to the client after a rebounce delay, at which point it is copied to
51 // mOrientation.
linyuh183cb712017-12-27 17:02:37 -080052 private int pendingOrientation;
53 private OrientationListener listener;
54 Handler handler =
Eric Erfanianccca3152017-02-22 16:32:36 -080055 new Handler() {
56 @Override
57 public void handleMessage(Message msg) {
58 switch (msg.what) {
59 case ORIENTATION_CHANGED:
60 synchronized (this) {
linyuh183cb712017-12-27 17:02:37 -080061 orientation = pendingOrientation;
Eric Erfanianccca3152017-02-22 16:32:36 -080062 if (DEBUG) {
linyuh183cb712017-12-27 17:02:37 -080063 LogUtil.d(
Eric Erfanianccca3152017-02-22 16:32:36 -080064 TAG,
65 "orientation: "
linyuh183cb712017-12-27 17:02:37 -080066 + (orientation == ORIENTATION_HORIZONTAL
Eric Erfanianccca3152017-02-22 16:32:36 -080067 ? "horizontal"
linyuh183cb712017-12-27 17:02:37 -080068 : (orientation == ORIENTATION_VERTICAL ? "vertical" : "unknown")));
Eric Erfanianccca3152017-02-22 16:32:36 -080069 }
linyuh183cb712017-12-27 17:02:37 -080070 if (listener != null) {
71 listener.orientationChanged(orientation);
Eric Erfanianccca3152017-02-22 16:32:36 -080072 }
73 }
74 break;
75 }
76 }
77 };
linyuh183cb712017-12-27 17:02:37 -080078 SensorEventListener sensorListener =
Eric Erfanianccca3152017-02-22 16:32:36 -080079 new SensorEventListener() {
80 @Override
81 public void onSensorChanged(SensorEvent event) {
82 onSensorEvent(event.values[0], event.values[1], event.values[2]);
83 }
84
85 @Override
86 public void onAccuracyChanged(Sensor sensor, int accuracy) {
87 // ignore
88 }
89 };
90
91 public AccelerometerListener(Context context) {
linyuh183cb712017-12-27 17:02:37 -080092 sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
93 sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
Eric Erfanianccca3152017-02-22 16:32:36 -080094 }
95
96 public void setListener(OrientationListener listener) {
linyuh183cb712017-12-27 17:02:37 -080097 this.listener = listener;
Eric Erfanianccca3152017-02-22 16:32:36 -080098 }
99
100 public void enable(boolean enable) {
101 if (DEBUG) {
linyuh183cb712017-12-27 17:02:37 -0800102 LogUtil.d(TAG, "enable(" + enable + ")");
Eric Erfanianccca3152017-02-22 16:32:36 -0800103 }
104 synchronized (this) {
105 if (enable) {
linyuh183cb712017-12-27 17:02:37 -0800106 orientation = ORIENTATION_UNKNOWN;
107 pendingOrientation = ORIENTATION_UNKNOWN;
108 sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
Eric Erfanianccca3152017-02-22 16:32:36 -0800109 } else {
linyuh183cb712017-12-27 17:02:37 -0800110 sensorManager.unregisterListener(sensorListener);
111 handler.removeMessages(ORIENTATION_CHANGED);
Eric Erfanianccca3152017-02-22 16:32:36 -0800112 }
113 }
114 }
115
116 private void setOrientation(int orientation) {
117 synchronized (this) {
linyuh183cb712017-12-27 17:02:37 -0800118 if (pendingOrientation == orientation) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800119 // Pending orientation has not changed, so do nothing.
120 return;
121 }
122
123 // Cancel any pending messages.
124 // We will either start a new timer or cancel alltogether
125 // if the orientation has not changed.
linyuh183cb712017-12-27 17:02:37 -0800126 handler.removeMessages(ORIENTATION_CHANGED);
Eric Erfanianccca3152017-02-22 16:32:36 -0800127
linyuh183cb712017-12-27 17:02:37 -0800128 if (this.orientation != orientation) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800129 // Set timer to send an event if the orientation has changed since its
130 // previously reported value.
linyuh183cb712017-12-27 17:02:37 -0800131 pendingOrientation = orientation;
132 final Message m = handler.obtainMessage(ORIENTATION_CHANGED);
Eric Erfanianccca3152017-02-22 16:32:36 -0800133 // set delay to our debounce timeout
134 int delay = (orientation == ORIENTATION_VERTICAL ? VERTICAL_DEBOUNCE : HORIZONTAL_DEBOUNCE);
linyuh183cb712017-12-27 17:02:37 -0800135 handler.sendMessageDelayed(m, delay);
Eric Erfanianccca3152017-02-22 16:32:36 -0800136 } else {
137 // no message is pending
linyuh183cb712017-12-27 17:02:37 -0800138 pendingOrientation = ORIENTATION_UNKNOWN;
Eric Erfanianccca3152017-02-22 16:32:36 -0800139 }
140 }
141 }
142
143 private void onSensorEvent(double x, double y, double z) {
144 if (VDEBUG) {
linyuh183cb712017-12-27 17:02:37 -0800145 LogUtil.d(TAG, "onSensorEvent(" + x + ", " + y + ", " + z + ")");
Eric Erfanianccca3152017-02-22 16:32:36 -0800146 }
147
148 // If some values are exactly zero, then likely the sensor is not powered up yet.
149 // ignore these events to avoid false horizontal positives.
150 if (x == 0.0 || y == 0.0 || z == 0.0) {
151 return;
152 }
153
154 // magnitude of the acceleration vector projected onto XY plane
155 final double xy = Math.hypot(x, y);
156 // compute the vertical angle
157 double angle = Math.atan2(xy, z);
158 // convert to degrees
159 angle = angle * 180.0 / Math.PI;
160 final int orientation =
161 (angle > VERTICAL_ANGLE ? ORIENTATION_VERTICAL : ORIENTATION_HORIZONTAL);
162 if (VDEBUG) {
linyuh183cb712017-12-27 17:02:37 -0800163 LogUtil.d(TAG, "angle: " + angle + " orientation: " + orientation);
Eric Erfanianccca3152017-02-22 16:32:36 -0800164 }
165 setOrientation(orientation);
166 }
167
168 public interface OrientationListener {
169
170 void orientationChanged(int orientation);
171 }
172}