InCallUI: SmartMute
Mute the incoming call by flipping the phone
AICP: Brought to N by combining into one commit
3a4c1f7b7b319a3bfd560423ae19e4da3f52eda1
9063092dfc3eac9bc30f73fdca40ec6fe1aa1f44
AICP: brought up to O
@eyosen: brought up to P
Change-Id: I3ff27450eecbf501fafb2d75317a0d7dd844e7b2
Signed-off-by: linuxxxxx <joey@cyanogenmoditalia.it>
Signed-off-by: blinoff82 <blinov@gmail.com>
Signed-off-by: DennySPB <dennyspb@gmail.com>
diff --git a/java/com/android/dialer/app/res/values-ru/syberia_strings.xml b/java/com/android/dialer/app/res/values-ru/syberia_strings.xml
deleted file mode 100644
index 6c08e48..0000000
--- a/java/com/android/dialer/app/res/values-ru/syberia_strings.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 Syberia 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.
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
- <!-- Proximity speaker -->
- <string name="speaker_settings_label">Датчик приближения и громкая связь</string>
- <string name="prox_auto_speaker_title">Включение громкой связи по датчику приближения</string>
- <string name="prox_auto_speaker_summary">Автоматически включать громкую связь, при удалении телефона от уха</string>
- <string name="prox_auto_speaker_delay_title">Задержка включения громкой связи</string>
- <string name="prox_auto_speaker_delay_dialog_title">Задержка включения громкой связи в (мс)</string>
- <string name="prox_auto_speaker_delay_summary">Громкая связь будет включена через <xliff:g id="number">%d</xliff:g> мс</string>
- <string name="prox_auto_speaker_incall_only_title">Только во время входящего вызова</string>
- <string name="prox_auto_speaker_incall_only_summary_on">При исходящих звонках функция активируется только после ответа на вызов</string>
- <string name="prox_auto_speaker_incall_only_summary_off">Функция активна при любых вызовах (по умолчанию)</string>
-
- <string name="prox_auto_answer_incall_only_title">Автоматический ответ</string>
- <string name="prox_auto_answer_incall_only_summary">Автоответ на входящий звонок с использованием датчика приближения</string>
-
- <string name="auto_answer_call_title">Автоответ с гарнитурой</string>
- <string name="auto_answer_call_summary">Автоответ на звонок при подключенной проводной или беспроводной гарнитуры</string>
- <string name="auto_answer_delay_title">Задержка автоответа</string>
- <string name="auto_answer_dialog_title">Задержка автоответа в (мс)</string>
- <string name="auto_answer_delay_summary">Автоответ будет включен через <xliff:g id="number">%d</xliff:g> мс</string>
-</resources>
\ No newline at end of file
diff --git a/java/com/android/dialer/app/res/values/bliss_strings.xml b/java/com/android/dialer/app/res/values/bliss_strings.xml
index bc13c91..f36fa40 100644
--- a/java/com/android/dialer/app/res/values/bliss_strings.xml
+++ b/java/com/android/dialer/app/res/values/bliss_strings.xml
@@ -46,4 +46,9 @@
<string name="auto_answer_delay_title">Autoanswer delay</string>
<string name="auto_answer_dialog_title">Autoanswer delay in (ms)</string>
<string name="auto_answer_delay_summary">Autoanswer will be activated in <xliff:g id="number">%d</xliff:g> ms</string>
+
+ <!-- Smart Options -->
+ <string name="smart_category_title">Gestures</string>
+ <string name="smart_mute_title">Smart mute</string>
+ <string name="smart_mute_summary">Mute the incoming call by flipping the device</string>
</resources>
diff --git a/java/com/android/dialer/app/res/xml/sound_settings.xml b/java/com/android/dialer/app/res/xml/sound_settings.xml
index b862fd8..974e0da 100644
--- a/java/com/android/dialer/app/res/xml/sound_settings.xml
+++ b/java/com/android/dialer/app/res/xml/sound_settings.xml
@@ -73,4 +73,17 @@
</PreferenceCategory>
+ <PreferenceCategory
+ android:key="dialer_general_smart_category_key"
+ android:title="@string/smart_category_title"
+ android:persistent="false">
+
+ <SwitchPreference
+ android:key="button_smart_mute"
+ android:title="@string/smart_mute_title"
+ android:summary="@string/smart_mute_summary"
+ android:defaultValue="false" />
+
+ </PreferenceCategory>
+
</PreferenceScreen>
diff --git a/java/com/android/dialer/app/settings/SoundSettingsFragment.java b/java/com/android/dialer/app/settings/SoundSettingsFragment.java
index 634f993..fd66b76 100644
--- a/java/com/android/dialer/app/settings/SoundSettingsFragment.java
+++ b/java/com/android/dialer/app/settings/SoundSettingsFragment.java
@@ -53,6 +53,8 @@
private static final int MSG_UPDATE_RINGTONE_SUMMARY = 1;
+ public static final String BUTTON_SMART_MUTE_KEY = "button_smart_mute";
+
private Preference ringtonePreference;
private final Handler ringtoneLookupComplete =
new Handler() {
diff --git a/java/com/android/incallui/AccelerometerListener.java b/java/com/android/incallui/AccelerometerListener.java
index 92e62b0..35a05b4 100644
--- a/java/com/android/incallui/AccelerometerListener.java
+++ b/java/com/android/incallui/AccelerometerListener.java
@@ -39,6 +39,7 @@
private static final boolean DEBUG = true;
private static final boolean VDEBUG = false;
private static final int ORIENTATION_CHANGED = 1234;
+ private static final int FACE_UP_CHANGED = 1235;
private static final int VERTICAL_DEBOUNCE = 100;
private static final int HORIZONTAL_DEBOUNCE = 500;
private static final double VERTICAL_ANGLE = 50.0;
@@ -50,7 +51,7 @@
// This is sent to the client after a rebounce delay, at which point it is copied to
// mOrientation.
private int pendingOrientation;
- private OrientationListener listener;
+ private ChangeListener listener;
Handler handler =
new Handler() {
@Override
@@ -68,10 +69,13 @@
: (orientation == ORIENTATION_VERTICAL ? "vertical" : "unknown")));
}
if (listener != null) {
- listener.orientationChanged(orientation);
+ listener.onOrientationChanged(orientation);
}
}
break;
+ case FACE_UP_CHANGED:
+ listener.onDeviceFlipped(msg.arg1 == 0);
+ break;
}
}
};
@@ -88,12 +92,33 @@
}
};
+ // Flip detection
+ private static final int FACE_UP_GRAVITY_THRESHOLD = 7;
+ private static final int FACE_DOWN_GRAVITY_THRESHOLD = -7;
+ private static final int SENSOR_SAMPLES = 3;
+ private static final int MIN_ACCEPT_COUNT = SENSOR_SAMPLES - 1;
+
+ private boolean mWasFaceUp;
+ private boolean[] mSamples = new boolean[SENSOR_SAMPLES];
+ private int mSampleIndex;
+
+ public interface ChangeListener {
+ void onOrientationChanged(int orientation);
+ void onDeviceFlipped(boolean faceDown);
+ }
+
public AccelerometerListener(Context context) {
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
- public void setListener(OrientationListener listener) {
+ public AccelerometerListener(Context context, ChangeListener listener) {
+ setListener(listener);
+ sensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+ sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ }
+
+ public void setListener(ChangeListener listener) {
this.listener = listener;
}
@@ -105,6 +130,8 @@
if (enable) {
orientation = ORIENTATION_UNKNOWN;
pendingOrientation = ORIENTATION_UNKNOWN;
+ mWasFaceUp = false;
+ resetFlipSamples();
sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
} else {
sensorManager.unregisterListener(sensorListener);
@@ -113,6 +140,22 @@
}
}
+ private void resetFlipSamples() {
+ for (int i = 0; i < SENSOR_SAMPLES; i++) {
+ mSamples[i] = false;
+ }
+ }
+
+ private boolean filterFlipSamples() {
+ int trues = 0;
+ for (int i = 0; i < mSamples.length; i++) {
+ if (mSamples[i]) {
+ ++trues;
+ }
+ }
+ return trues >= MIN_ACCEPT_COUNT;
+ }
+
private void setOrientation(int orientation) {
synchronized (this) {
if (pendingOrientation == orientation) {
@@ -140,6 +183,17 @@
}
}
+ private void setIsFaceUp(boolean faceUp) {
+ synchronized (this) {
+ if (mWasFaceUp != faceUp) {
+ handler.removeMessages(FACE_UP_CHANGED);
+ handler.obtainMessage(FACE_UP_CHANGED, faceUp ? 1 : 0, 0).sendToTarget();
+ mWasFaceUp = faceUp;
+ resetFlipSamples();
+ }
+ }
+ }
+
private void onSensorEvent(double x, double y, double z) {
if (VDEBUG) {
LogUtil.d(TAG, "onSensorEvent(" + x + ", " + y + ", " + z + ")");
@@ -163,10 +217,24 @@
LogUtil.d(TAG, "angle: " + angle + " orientation: " + orientation);
}
setOrientation(orientation);
- }
- public interface OrientationListener {
+ boolean nowFaceUp, wasFaceUp;
+ synchronized (this) {
+ nowFaceUp = wasFaceUp = mWasFaceUp;
+ }
- void orientationChanged(int orientation);
+ if (!wasFaceUp) {
+ // Check if its face up enough.
+ mSamples[mSampleIndex] = z > FACE_UP_GRAVITY_THRESHOLD;
+ } else {
+ // Check if its face down enough.
+ mSamples[mSampleIndex] = z < FACE_DOWN_GRAVITY_THRESHOLD;
+ }
+ if (filterFlipSamples()) {
+ nowFaceUp = !wasFaceUp;
+ }
+
+ mSampleIndex = ((mSampleIndex + 1) % SENSOR_SAMPLES);
+ setIsFaceUp(nowFaceUp);
}
}
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index 4e90eb6..4ddbef2 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -18,10 +18,12 @@
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Trace;
+import android.preference.PreferenceManager;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -94,7 +96,8 @@
* presenters that want to listen in on the in-call state changes. TODO: This class has become more
* of a state machine at this point. Consider renaming.
*/
-public class InCallPresenter implements CallList.Listener, AudioModeProvider.AudioModeListener {
+public class InCallPresenter implements CallList.Listener, AudioModeProvider.AudioModeListener,
+ AccelerometerListener.ChangeListener {
private static final String PIXEL2017_SYSTEM_FEATURE =
"com.google.android.feature.PIXEL_2017_EXPERIENCE";
private static final String CALL_CONFIGURATION_EXTRA = "call_configuration";
@@ -197,6 +200,7 @@
};
private InCallState inCallState = InCallState.NO_CALLS;
private ProximitySensor proximitySensor;
+ private AccelerometerListener mAccelerometerListener;
private final PseudoScreenState pseudoScreenState = new PseudoScreenState();
private boolean serviceConnected;
private InCallCameraManager inCallCameraManager;
@@ -368,6 +372,7 @@
this.proximitySensor = proximitySensor;
addListener(this.proximitySensor);
+ mAccelerometerListener = new AccelerometerListener(context, this);
if (themeColorManager == null) {
themeColorManager = new ThemeColorManager(new InCallUIMaterialColorMapUtils(this.context));
@@ -861,6 +866,10 @@
LogUtil.d(
"InCallPresenter.onCallListChange", "onCallListChange newState changed to " + newState);
+ if (!newState.isIncoming() && mAccelerometerListener != null) {
+ mAccelerometerListener.enable(false);
+ }
+
// Set the new state before announcing it to the world
LogUtil.i(
"InCallPresenter.onCallListChange",
@@ -959,6 +968,10 @@
"InCallPresenter.onIncomingCall", "Phone switching state: " + oldState + " -> " + newState);
inCallState = newState;
+ if (newState.isIncoming() && mAccelerometerListener != null) {
+ mAccelerometerListener.enable(true);
+ }
+
Trace.beginSection("listener.onIncomingCall");
for (IncomingCallListener listener : incomingCallListeners) {
listener.onIncomingCall(oldState, inCallState, call);
@@ -1052,6 +1065,22 @@
&& (number.length() <= 8 || number.startsWith("*#*#") || number.endsWith("#*#*"));
}
+ public void onOrientationChanged(int orientation) {
+ // ignored
+ }
+
+ @Override
+ public void onDeviceFlipped(boolean faceDown) {
+ if (!faceDown) {
+ return;
+ }
+
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ if (prefs.getBoolean("button_smart_mute", false)) {
+ TelecomUtil.silenceRinger(context);
+ }
+ }
+
/** Given the call list, return the state in which the in-call screen should be. */
public InCallState getPotentialStateFromCallList(CallList callList) {
@@ -1336,6 +1365,9 @@
// (1) Attempt to answer a call
if (incomingCall != null) {
incomingCall.answer(VideoProfile.STATE_AUDIO_ONLY);
+ if (mAccelerometerListener != null) {
+ mAccelerometerListener.enable(false);
+ }
return true;
}
@@ -1641,6 +1673,11 @@
}
proximitySensor = null;
+ if (mAccelerometerListener != null) {
+ mAccelerometerListener.enable(false);
+ mAccelerometerListener = null;
+ }
+
if (statusBarNotifier != null) {
removeListener(statusBarNotifier);
EnrichedCallComponent.get(context)
diff --git a/java/com/android/incallui/ProximitySensor.java b/java/com/android/incallui/ProximitySensor.java
index 941dc0b..580e8c7 100644
--- a/java/com/android/incallui/ProximitySensor.java
+++ b/java/com/android/incallui/ProximitySensor.java
@@ -50,7 +50,7 @@
* and disabled. Most of that state is fed into this class through public methods.
*/
public class ProximitySensor
- implements AccelerometerListener.OrientationListener, InCallStateListener, AudioModeListener, SensorEventListener {
+ implements AccelerometerListener.ChangeListener, InCallStateListener, AudioModeListener, SensorEventListener {
private static final String TAG = ProximitySensor.class.getSimpleName();
private static final String PREF_KEY_DISABLE_PROXI_SENSOR = "disable_proximity_sensor_key";
@@ -160,11 +160,16 @@
/** Called to identify when the device is laid down flat. */
@Override
- public void orientationChanged(int orientation) {
+ public void onOrientationChanged(int orientation) {
this.orientation = orientation;
updateProximitySensorMode();
}
+ @Override
+ public void onDeviceFlipped(boolean faceDown) {
+ // ignored
+ }
+
/** Called to keep track of the overall UI state. */
@Override
public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {