Flip to Mute/Reject Call [3/3]
Ported over from SlimKat implementation (thanks Kufi)
Original message in 4.4:
Ported over from 4.2 implementation (thanks sasikumardr for that)
Original author of this patch was bugadani
We did just a cleanup
Provide easy mute and dismiss functionality for the phone
application.
Available actions:
0: mute ringer
1: dismiss call
2: no action (default)
Change-Id: I744251f323f852bb47b9031bad52d261a1549f34
Signed-off-by: Pafcholini <nadyaivanova14@gmail.com>
diff --git a/src/com/android/incallui/AccelerometerListener.java b/src/com/android/incallui/AccelerometerListener.java
index b5ad296..40186bd 100644
--- a/src/com/android/incallui/AccelerometerListener.java
+++ b/src/com/android/incallui/AccelerometerListener.java
@@ -23,6 +23,9 @@
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.telecom.TelecomManager;
import android.util.Log;
/**
@@ -59,12 +62,24 @@
private static final int HORIZONTAL_DEBOUNCE = 500;
private static final double VERTICAL_ANGLE = 50.0;
+ // Flip action IDs
+ private static final int MUTE_RINGER = 0;
+ private static final int DISMISS_CALL = 1;
+ private static final int RINGING_NO_ACTION = 2;
+
+ private Context mContext;
+
public interface OrientationListener {
public void orientationChanged(int orientation);
}
+ private interface ResettableSensorEventListener extends SensorEventListener {
+ public void reset();
+ }
+
public AccelerometerListener(Context context) {
- mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ mContext = context;
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
@@ -87,6 +102,25 @@
}
}
+ public void enableSensor(boolean enable) {
+ if (DEBUG) Log.d(TAG, "enableSensor(" + enable + ")");
+ int action = getFlipAction();
+ synchronized (this) {
+ if (enable) {
+ if (action != RINGING_NO_ACTION) {
+ mFlipListener.reset();
+ mSensorManager.registerListener(mFlipListener,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ } else {
+ if (action != RINGING_NO_ACTION) {
+ mSensorManager.unregisterListener(mFlipListener);
+ }
+ }
+ }
+ }
+
private void setOrientation(int orientation) {
synchronized (this) {
if (mPendingOrientation == orientation) {
@@ -145,6 +179,111 @@
}
};
+ private final ResettableSensorEventListener
+ mFlipListener = new ResettableSensorEventListener() {
+ // Our accelerometers are not quite accurate.
+ private static final int FACE_UP_GRAVITY_THRESHOLD = 7;
+ private static final int FACE_DOWN_GRAVITY_THRESHOLD = -7;
+ private static final int TILT_THRESHOLD = 3;
+ private static final int SENSOR_SAMPLES = 3;
+ private static final int MIN_ACCEPT_COUNT = SENSOR_SAMPLES - 1;
+
+ private boolean mStopped;
+ private boolean mWasFaceUp;
+ private boolean[] mSamples = new boolean[SENSOR_SAMPLES];
+ private int mSampleIndex;
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int acc) {
+ }
+
+ @Override
+ public void reset() {
+ mWasFaceUp = false;
+ mStopped = false;
+ for (int i = 0; i < SENSOR_SAMPLES; i++) {
+ mSamples[i] = false;
+ }
+ }
+
+ private boolean filterSamples() {
+ int trues = 0;
+ for (boolean sample : mSamples) {
+ if(sample) {
+ ++trues;
+ }
+ }
+ return trues >= MIN_ACCEPT_COUNT;
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (mStopped) {
+ return;
+ }
+ // Add a sample overwriting the oldest one. Several samples
+ // are used to avoid the erroneous values the sensor sometimes
+ // returns.
+ float z = event.values[2];
+
+ if (!mWasFaceUp) {
+ // Check if its face up enough.
+ mSamples[mSampleIndex] = z > FACE_UP_GRAVITY_THRESHOLD;
+
+ // face up
+ if (filterSamples()) {
+ mWasFaceUp = true;
+ for (int i = 0; i < SENSOR_SAMPLES; i++) {
+ mSamples[i] = false;
+ }
+ }
+ } else {
+ // Check if its face down enough.
+ mSamples[mSampleIndex] = z < FACE_DOWN_GRAVITY_THRESHOLD;
+
+ // face down
+ if (filterSamples()) {
+ mStopped = true;
+ handleAction();
+ }
+ }
+
+ mSampleIndex = ((mSampleIndex + 1) % SENSOR_SAMPLES);
+ }
+ };
+
+ public void handleAction() {
+ switch(getFlipAction()) {
+ case MUTE_RINGER:
+ {
+ TelecomManager tm =
+ (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+ if (tm != null) {
+ tm.silenceRinger();
+ }
+ }
+ break;
+ case DISMISS_CALL:
+ {
+ TelecomManager tm =
+ (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
+ if (tm != null) {
+ tm.endCall();
+ }
+ }
+ break;
+ case RINGING_NO_ACTION:
+ default:
+ //no action
+ break;
+ }
+ }
+
+ private int getFlipAction(){
+ return Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.CALL_FLIP_ACTION_KEY, RINGING_NO_ACTION);
+ }
+
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/src/com/android/incallui/InCallPresenter.java b/src/com/android/incallui/InCallPresenter.java
index 07da827..da1e49a 100644
--- a/src/com/android/incallui/InCallPresenter.java
+++ b/src/com/android/incallui/InCallPresenter.java
@@ -97,6 +97,7 @@
private CallList mCallList;
private InCallActivity mInCallActivity;
private InCallState mInCallState = InCallState.NO_CALLS;
+ private AccelerometerListener mAccelerometerListener;
private ProximitySensor mProximitySensor;
private boolean mServiceConnected = false;
private boolean mAccountSelectionCancelled = false;
@@ -238,6 +239,8 @@
mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP, "InCallPresenter");
+ mAccelerometerListener = new AccelerometerListener(context);
+
mCallList = callList;
// This only gets called by the service so this is okay.
@@ -472,6 +475,10 @@
Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
mInCallState = newState;
+ if (!newState.isIncoming() && mAccelerometerListener != null) {
+ mAccelerometerListener.enableSensor(false);
+ }
+
// notify listeners of new state
for (InCallStateListener listener : mListeners) {
Log.d(this, "Notify " + listener + " of state " + mInCallState.toString());
@@ -501,6 +508,10 @@
Log.i(this, "Phone switching state: " + oldState + " -> " + newState);
mInCallState = newState;
+ if (newState.isIncoming() && mAccelerometerListener != null) {
+ mAccelerometerListener.enableSensor(true);
+ }
+
for (IncomingCallListener listener : mIncomingCallListeners) {
listener.onIncomingCall(oldState, mInCallState, call);
}
@@ -720,6 +731,11 @@
* Answers any incoming call.
*/
public void answerIncomingCall(Context context, int videoState) {
+ // Just in case
+ if (mAccelerometerListener != null) {
+ mAccelerometerListener.enableSensor(false);
+ }
+
// By the time we receive this intent, we could be shut down and call list
// could be null. Bail in those cases.
if (mCallList == null) {
@@ -738,6 +754,11 @@
* Declines any incoming call.
*/
public void declineIncomingCall(Context context) {
+ // Just in case
+ if (mAccelerometerListener != null) {
+ mAccelerometerListener.enableSensor(false);
+ }
+
// By the time we receive this intent, we could be shut down and call list
// could be null. Bail in those cases.
if (mCallList == null) {
@@ -946,6 +967,9 @@
if (incomingCall != null) {
TelecomAdapter.getInstance().answerCall(
incomingCall.getId(), VideoProfile.STATE_AUDIO_ONLY);
+ if (mAccelerometerListener != null) {
+ mAccelerometerListener.enableSensor(false);
+ }
return true;
}
@@ -1367,6 +1391,8 @@
mWakeLock = null;
mPowerManager = null;
+ mAccelerometerListener = null;
+
mAudioModeProvider = null;
if (mStatusBarNotifier != null) {