Loading core/res/res/values/config.xml +10 −0 Original line number Original line Diff line number Diff line Loading @@ -2637,4 +2637,14 @@ <bool name="config_regional_hotspot_show_broadcast_ssid_checkbox">false</bool> <bool name="config_regional_hotspot_show_broadcast_ssid_checkbox">false</bool> <bool name="config_regional_hotspot_show_notification_when_turn_on">false</bool> <bool name="config_regional_hotspot_show_notification_when_turn_on">false</bool> <bool name="config_passpoint_setting_on">false</bool> <bool name="config_passpoint_setting_on">false</bool> <!-- Emergency Number to be invoked when Power key is pressed. Default value is set to 112 as this FR is mainly intended for Indian market--> <string name="power_key_emergency_number">112</string> <!-- Number of power key hits to invoke emergency call --> <integer name="power_key_hits_emergency">3</integer> <!-- Allow the gesture to tap the power button N times to start the Emergency Call while the device is non-interactive. --> <bool name="config_emergencyCallOnPowerkeyTapGestureEnabled">false</bool> </resources> </resources> core/res/res/values/symbols.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -2729,4 +2729,8 @@ <java-symbol type="integer" name="wifi_hotspot_security_type" /> <java-symbol type="integer" name="wifi_hotspot_security_type" /> <java-symbol type="string" name="def_wifi_wifihotspot_pass" /> <java-symbol type="string" name="def_wifi_wifihotspot_pass" /> <java-symbol type="string" name="def_wifi_direct_name" /> <java-symbol type="string" name="def_wifi_direct_name" /> <java-symbol type="string" name="power_key_emergency_number" /> <java-symbol type="integer" name="power_key_hits_emergency" /> <java-symbol type="bool" name="config_emergencyCallOnPowerkeyTapGestureEnabled" /> </resources> </resources> services/core/java/com/android/server/GestureLauncherService.java +71 −10 Original line number Original line Diff line number Diff line Loading @@ -28,12 +28,14 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.SensorManager; import android.net.Uri; import android.os.Handler; import android.os.Handler; import android.os.PowerManager; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.os.SystemClock; import android.os.SystemProperties; import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.util.MutableBoolean; import android.util.MutableBoolean; import android.util.Slog; import android.util.Slog; import android.view.KeyEvent; import android.view.KeyEvent; Loading @@ -42,6 +44,8 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.statusbar.StatusBarManagerInternal; import java.util.Arrays; /** /** * The service that listens for gestures detected in sensor firmware and starts the intent * The service that listens for gestures detected in sensor firmware and starts the intent * accordingly. * accordingly. Loading Loading @@ -106,6 +110,20 @@ public class GestureLauncherService extends SystemService { private boolean mCameraDoubleTapPowerEnabled; private boolean mCameraDoubleTapPowerEnabled; private long mLastPowerDown; private long mLastPowerDown; /** * Whether EmergencyCall on power button tap gesture is currently enabled; */ private boolean mIsEmergencyOnPowerKeyTapEnabled; private long[] mHits; private long mDuration; private String mEmergencyNumber; /** * Time in milliseconds in which interval power tap must be pressed to make * an emergency call. */ private static final long EMERGENCY_CALL_POWER_KEY_TAP_INTERVAL = 400; public GestureLauncherService(Context context) { public GestureLauncherService(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -129,7 +147,7 @@ public class GestureLauncherService extends SystemService { "GestureLauncherService"); "GestureLauncherService"); updateCameraRegistered(); updateCameraRegistered(); updateCameraDoubleTapPowerEnabled(); updateCameraDoubleTapPowerEnabled(); updateEmergencyCallTapPowerEnabled(); mUserId = ActivityManager.getCurrentUser(); mUserId = ActivityManager.getCurrentUser(); mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED)); mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED)); registerContentObservers(); registerContentObservers(); Loading Loading @@ -244,11 +262,33 @@ public class GestureLauncherService extends SystemService { com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } } public static boolean isEmergencyOnpowerButtonTapEnabled(Resources resources) { return SystemProperties.getBoolean( "persist.sys.ecall_pwr_key_press", false) || resources.getBoolean( com.android.internal.R.bool.config_emergencyCallOnPowerkeyTapGestureEnabled); } /** /** * Whether GestureLauncherService should be enabled according to system properties. * Whether GestureLauncherService should be enabled according to system properties. */ */ public static boolean isGestureLauncherEnabled(Resources resources) { public static boolean isGestureLauncherEnabled(Resources resources) { return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources); return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) || isEmergencyOnpowerButtonTapEnabled(resources); } private void updateEmergencyCallTapPowerEnabled() { Resources resources = mContext.getResources(); mIsEmergencyOnPowerKeyTapEnabled = isEmergencyOnpowerButtonTapEnabled(resources); mEmergencyNumber = resources.getString( com.android.internal.R.string.power_key_emergency_number); int hits = resources.getInteger( com.android.internal.R.integer.power_key_hits_emergency); mDuration = hits * EMERGENCY_CALL_POWER_KEY_TAP_INTERVAL; mHits = new long[hits]; Slog.d(TAG, "Gesture launcher mEmergencyNumber = " + mEmergencyNumber + " hits = " + hits); } } public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, Loading @@ -258,7 +298,19 @@ public class GestureLauncherService extends SystemService { long doubleTapInterval; long doubleTapInterval; synchronized (this) { synchronized (this) { doubleTapInterval = event.getEventTime() - mLastPowerDown; doubleTapInterval = event.getEventTime() - mLastPowerDown; if (mCameraDoubleTapPowerEnabled if (mIsEmergencyOnPowerKeyTapEnabled) { System.arraycopy(mHits, 1, mHits, 0, mHits.length-1); mHits[mHits.length-1] = SystemClock.uptimeMillis(); for (int i = 0 ; i < mHits.length ; i++) { Slog.i(TAG, "mHits[" + i + "] = " + mHits[i] + "ms"); } if (mHits[0] >= (SystemClock.uptimeMillis()-mDuration)) { launched = true; intercept = interactive; Arrays.fill(mHits,0); } } else if (mCameraDoubleTapPowerEnabled && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { launched = true; launched = true; intercept = interactive; intercept = interactive; Loading @@ -266,15 +318,24 @@ public class GestureLauncherService extends SystemService { mLastPowerDown = event.getEventTime(); mLastPowerDown = event.getEventTime(); } } if (launched) { if (launched) { if (mIsEmergencyOnPowerKeyTapEnabled && !TextUtils.isEmpty(mEmergencyNumber)) { Slog.i(TAG, "Power button Triple tap gesture detected, launching Emergency Call"); Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts("tel", mEmergencyNumber, null)); getContext().startActivity(intent); } else { Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" + doubleTapInterval + "ms"); + doubleTapInterval + "ms"); launched = handleCameraLaunchGesture(false /* useWakelock */, launched = handleCameraLaunchGesture(false /* useWakelock */, StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); if (launched) { if (launched) { MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) doubleTapInterval); (int) doubleTapInterval); } } } } } MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval); MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval); outLaunched.value = launched; outLaunched.value = launched; return intercept && launched; return intercept && launched; Loading Loading
core/res/res/values/config.xml +10 −0 Original line number Original line Diff line number Diff line Loading @@ -2637,4 +2637,14 @@ <bool name="config_regional_hotspot_show_broadcast_ssid_checkbox">false</bool> <bool name="config_regional_hotspot_show_broadcast_ssid_checkbox">false</bool> <bool name="config_regional_hotspot_show_notification_when_turn_on">false</bool> <bool name="config_regional_hotspot_show_notification_when_turn_on">false</bool> <bool name="config_passpoint_setting_on">false</bool> <bool name="config_passpoint_setting_on">false</bool> <!-- Emergency Number to be invoked when Power key is pressed. Default value is set to 112 as this FR is mainly intended for Indian market--> <string name="power_key_emergency_number">112</string> <!-- Number of power key hits to invoke emergency call --> <integer name="power_key_hits_emergency">3</integer> <!-- Allow the gesture to tap the power button N times to start the Emergency Call while the device is non-interactive. --> <bool name="config_emergencyCallOnPowerkeyTapGestureEnabled">false</bool> </resources> </resources>
core/res/res/values/symbols.xml +4 −0 Original line number Original line Diff line number Diff line Loading @@ -2729,4 +2729,8 @@ <java-symbol type="integer" name="wifi_hotspot_security_type" /> <java-symbol type="integer" name="wifi_hotspot_security_type" /> <java-symbol type="string" name="def_wifi_wifihotspot_pass" /> <java-symbol type="string" name="def_wifi_wifihotspot_pass" /> <java-symbol type="string" name="def_wifi_direct_name" /> <java-symbol type="string" name="def_wifi_direct_name" /> <java-symbol type="string" name="power_key_emergency_number" /> <java-symbol type="integer" name="power_key_hits_emergency" /> <java-symbol type="bool" name="config_emergencyCallOnPowerkeyTapGestureEnabled" /> </resources> </resources>
services/core/java/com/android/server/GestureLauncherService.java +71 −10 Original line number Original line Diff line number Diff line Loading @@ -28,12 +28,14 @@ import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.hardware.SensorManager; import android.net.Uri; import android.os.Handler; import android.os.Handler; import android.os.PowerManager; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.PowerManager.WakeLock; import android.os.SystemClock; import android.os.SystemClock; import android.os.SystemProperties; import android.os.SystemProperties; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.util.MutableBoolean; import android.util.MutableBoolean; import android.util.Slog; import android.util.Slog; import android.view.KeyEvent; import android.view.KeyEvent; Loading @@ -42,6 +44,8 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.statusbar.StatusBarManagerInternal; import java.util.Arrays; /** /** * The service that listens for gestures detected in sensor firmware and starts the intent * The service that listens for gestures detected in sensor firmware and starts the intent * accordingly. * accordingly. Loading Loading @@ -106,6 +110,20 @@ public class GestureLauncherService extends SystemService { private boolean mCameraDoubleTapPowerEnabled; private boolean mCameraDoubleTapPowerEnabled; private long mLastPowerDown; private long mLastPowerDown; /** * Whether EmergencyCall on power button tap gesture is currently enabled; */ private boolean mIsEmergencyOnPowerKeyTapEnabled; private long[] mHits; private long mDuration; private String mEmergencyNumber; /** * Time in milliseconds in which interval power tap must be pressed to make * an emergency call. */ private static final long EMERGENCY_CALL_POWER_KEY_TAP_INTERVAL = 400; public GestureLauncherService(Context context) { public GestureLauncherService(Context context) { super(context); super(context); mContext = context; mContext = context; Loading @@ -129,7 +147,7 @@ public class GestureLauncherService extends SystemService { "GestureLauncherService"); "GestureLauncherService"); updateCameraRegistered(); updateCameraRegistered(); updateCameraDoubleTapPowerEnabled(); updateCameraDoubleTapPowerEnabled(); updateEmergencyCallTapPowerEnabled(); mUserId = ActivityManager.getCurrentUser(); mUserId = ActivityManager.getCurrentUser(); mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED)); mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED)); registerContentObservers(); registerContentObservers(); Loading Loading @@ -244,11 +262,33 @@ public class GestureLauncherService extends SystemService { com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } } public static boolean isEmergencyOnpowerButtonTapEnabled(Resources resources) { return SystemProperties.getBoolean( "persist.sys.ecall_pwr_key_press", false) || resources.getBoolean( com.android.internal.R.bool.config_emergencyCallOnPowerkeyTapGestureEnabled); } /** /** * Whether GestureLauncherService should be enabled according to system properties. * Whether GestureLauncherService should be enabled according to system properties. */ */ public static boolean isGestureLauncherEnabled(Resources resources) { public static boolean isGestureLauncherEnabled(Resources resources) { return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources); return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) || isEmergencyOnpowerButtonTapEnabled(resources); } private void updateEmergencyCallTapPowerEnabled() { Resources resources = mContext.getResources(); mIsEmergencyOnPowerKeyTapEnabled = isEmergencyOnpowerButtonTapEnabled(resources); mEmergencyNumber = resources.getString( com.android.internal.R.string.power_key_emergency_number); int hits = resources.getInteger( com.android.internal.R.integer.power_key_hits_emergency); mDuration = hits * EMERGENCY_CALL_POWER_KEY_TAP_INTERVAL; mHits = new long[hits]; Slog.d(TAG, "Gesture launcher mEmergencyNumber = " + mEmergencyNumber + " hits = " + hits); } } public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, Loading @@ -258,7 +298,19 @@ public class GestureLauncherService extends SystemService { long doubleTapInterval; long doubleTapInterval; synchronized (this) { synchronized (this) { doubleTapInterval = event.getEventTime() - mLastPowerDown; doubleTapInterval = event.getEventTime() - mLastPowerDown; if (mCameraDoubleTapPowerEnabled if (mIsEmergencyOnPowerKeyTapEnabled) { System.arraycopy(mHits, 1, mHits, 0, mHits.length-1); mHits[mHits.length-1] = SystemClock.uptimeMillis(); for (int i = 0 ; i < mHits.length ; i++) { Slog.i(TAG, "mHits[" + i + "] = " + mHits[i] + "ms"); } if (mHits[0] >= (SystemClock.uptimeMillis()-mDuration)) { launched = true; intercept = interactive; Arrays.fill(mHits,0); } } else if (mCameraDoubleTapPowerEnabled && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { && doubleTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) { launched = true; launched = true; intercept = interactive; intercept = interactive; Loading @@ -266,15 +318,24 @@ public class GestureLauncherService extends SystemService { mLastPowerDown = event.getEventTime(); mLastPowerDown = event.getEventTime(); } } if (launched) { if (launched) { if (mIsEmergencyOnPowerKeyTapEnabled && !TextUtils.isEmpty(mEmergencyNumber)) { Slog.i(TAG, "Power button Triple tap gesture detected, launching Emergency Call"); Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts("tel", mEmergencyNumber, null)); getContext().startActivity(intent); } else { Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" Slog.i(TAG, "Power button double tap gesture detected, launching camera. Interval=" + doubleTapInterval + "ms"); + doubleTapInterval + "ms"); launched = handleCameraLaunchGesture(false /* useWakelock */, launched = handleCameraLaunchGesture(false /* useWakelock */, StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); if (launched) { if (launched) { MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, MetricsLogger.action(mContext, MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) doubleTapInterval); (int) doubleTapInterval); } } } } } MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval); MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval); outLaunched.value = launched; outLaunched.value = launched; return intercept && launched; return intercept && launched; Loading