diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3608280c7f94b26cc8ad8e5ff963c8e92109d92f..7119aefaf8f8a4cdd5faaa95828c77ed7ee34dd7 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5605,6 +5605,27 @@ public final class Settings { */ public static final String SWAP_VOLUME_KEYS_ON_ROTATION = "swap_volume_keys_on_rotation"; + /** + * Whether to wake the screen with the camera key half-press. + * 0 = 0ff, 1 = on + * @hide + */ + public static final String CAMERA_WAKE_SCREEN = "camera_wake_screen"; + + /** + * Whether or not to send device back to sleep if Camera button is released ("Peek") + * 0 = 0ff, 1 = on + * @hide + */ + public static final String CAMERA_SLEEP_ON_RELEASE = "camera_sleep_on_release"; + + /** + * Whether to launch secure camera app when key is longpressed + * 0 = 0ff, 1 = on + * @hide + */ + public static final String CAMERA_LAUNCH = "camera_launch"; + /** * IMPORTANT: If you add a new public settings you also have to add it to * PUBLIC_SETTINGS below. If the new setting is hidden you have to add diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 72decc96d784904d75d90b44c073ca4c1cec74e6..63fa3323b5b5dece36bb7c4dbca0096ccba9113a 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1993,6 +1993,7 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final boolean isWakeKey(int keyCode) { switch (keyCode) { case KeyEvent.KEYCODE_CAMERA: + case KeyEvent.KEYCODE_FOCUS: case KeyEvent.KEYCODE_MENU: case KeyEvent.KEYCODE_PAIRING: case KeyEvent.KEYCODE_STEM_1: diff --git a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java index a09c8236b47d1cba3ee5785c246354690d3fc9c4..e5e49955cf10af0c847888d139f1c805d8856aa5 100644 --- a/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java +++ b/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java @@ -144,18 +144,6 @@ public class PhoneFallbackEventHandler implements FallbackEventHandler { dispatcher.startTracking(event, this); } else if (event.isLongPress() && dispatcher.isTracking(event)) { dispatcher.performedLongPress(event); - if (isUserSetupComplete()) { - mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - // Broadcast an intent that the Camera button was longpressed - Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - intent.putExtra(Intent.EXTRA_KEY_EVENT, event); - mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF, - null, null, null, 0, null, null); - } else { - Log.i(TAG, "Not dispatching CAMERA long press because user " - + "setup is in progress."); - } } return true; } diff --git a/core/res/res/values/lmodroid_config.xml b/core/res/res/values/lmodroid_config.xml index 47945ba897410069d772fcc419d08ba156a01fea..8a4c2db6b9502245761bca450513c69f87ca146d 100644 --- a/core/res/res/values/lmodroid_config.xml +++ b/core/res/res/values/lmodroid_config.xml @@ -138,4 +138,8 @@ --> <integer name="config_longPressOnAppSwitchBehavior">0</integer> + <!-- Indicates that the device has Single-stage Camera key + (without "Focus" state) instead of Dual-stage. --> + <bool name="config_singleStageCameraKey">false</bool> + </resources> diff --git a/core/res/res/values/lmodroid_symbols.xml b/core/res/res/values/lmodroid_symbols.xml index 2eb24348268902f61cc427048e46f9f105059680..e53fcf0eb92bba364cfb8f8272ff3254cb662077 100644 --- a/core/res/res/values/lmodroid_symbols.xml +++ b/core/res/res/values/lmodroid_symbols.xml @@ -56,4 +56,7 @@ <java-symbol type="integer" name="config_longPressOnMenuBehavior" /> <java-symbol type="integer" name="config_longPressOnAppSwitchBehavior" /> + <!-- Camera key type --> + <java-symbol type="bool" name="config_singleStageCameraKey" /> + </resources> diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index cbd53de2d9aee70066b94c039ecc9c65e9a562c7..b4b0a9bae6d1cf4becc1d3f53170522ffa3cdf2b 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -531,8 +531,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mWakeOnHomeKeyPress; boolean mWakeOnMenuKeyPress; boolean mWakeOnAppSwitchKeyPress; + boolean mWakeOnCameraKeyPress; boolean mWakeOnVolumeKeyPress; + // Camera button control flags and actions + boolean mCameraLaunch; + boolean mCameraSleepOnRelease; + boolean mFocusReleasedGoToSleep; + boolean mIsFocusPressed; + boolean mIsLongPress; + // During wakeup by volume keys, we still need to capture subsequent events // until the key is released. This is required since the beep sound is produced // post keypressed. @@ -680,6 +688,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // LMODroid additions private static final int MSG_TOGGLE_TORCH = 100; + private static final int MSG_CAMERA_LONG_PRESS = 101; private CameraManager mCameraManager; private String mRearFlashCameraId; @@ -761,6 +770,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_TOGGLE_TORCH: toggleTorch(); break; + case MSG_CAMERA_LONG_PRESS: + KeyEvent event = (KeyEvent) msg.obj; + mIsLongPress = true; + break; } } } @@ -789,6 +802,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_WAKE_SCREEN), false, this, + UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_SLEEP_ON_RELEASE), false, this, + UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.System.getUriFor( + Settings.System.CAMERA_LAUNCH), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.RING_HOME_BUTTON_BEHAVIOR), false, this, UserHandle.USER_ALL); @@ -2484,6 +2506,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { mVolumeAnswerCall = (Settings.System.getIntForUser(resolver, Settings.System.VOLUME_ANSWER_CALL, 0, UserHandle.USER_CURRENT) == 1) && ((mDeviceHardwareWakeKeys & KEY_MASK_VOLUME) != 0); + mWakeOnCameraKeyPress = (Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_WAKE_SCREEN, 0, UserHandle.USER_CURRENT) == 1) + && ((mDeviceHardwareWakeKeys & KEY_MASK_CAMERA) != 0); + mCameraSleepOnRelease = mWakeOnCameraKeyPress && + Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_SLEEP_ON_RELEASE, 0, + UserHandle.USER_CURRENT) == 1; + mCameraLaunch = Settings.System.getIntForUser(resolver, + Settings.System.CAMERA_LAUNCH, 0, + UserHandle.USER_CURRENT) == 1; // Configure wake gesture. boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver, @@ -3924,14 +3956,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int displayId = event.getDisplayId(); final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; + // If screen is off then we treat the case where the keyguard is open but hidden + // the same as if it were open and in front. + // This will prevent any keys other than the power button from waking the screen + // when the keyguard is hidden by another activity. + final boolean keyguardActive = (mKeyguardDelegate != null + && (interactive ? isKeyguardShowingAndNotOccluded() : + mKeyguardDelegate.isShowing())); + if (DEBUG_INPUT) { - // If screen is off then we treat the case where the keyguard is open but hidden - // the same as if it were open and in front. - // This will prevent any keys other than the power button from waking the screen - // when the keyguard is hidden by another activity. - final boolean keyguardActive = (mKeyguardDelegate != null - && (interactive ? isKeyguardShowingAndNotOccluded() : - mKeyguardDelegate.isShowing())); Log.d(TAG, "interceptKeyTq keycode=" + keyCode + " interactive=" + interactive + " keyguardActive=" + keyguardActive + " policyFlags=" + Integer.toHexString(policyFlags)); @@ -4162,6 +4195,50 @@ public class PhoneWindowManager implements WindowManagerPolicy { } break; + case KeyEvent.KEYCODE_FOCUS: + if (down && !interactive && mCameraSleepOnRelease) { + mIsFocusPressed = true; + } else if (!down) { + // Check if screen is fully on before letting the device go to sleep + if (mDefaultDisplayPolicy.isScreenOnFully() && mIsFocusPressed) { + mPowerManager.goToSleep(SystemClock.uptimeMillis()); + } else if (!interactive && mCameraSleepOnRelease) { + mFocusReleasedGoToSleep = true; + } + mIsFocusPressed = false; + } + break; + + case KeyEvent.KEYCODE_CAMERA: + if (down && mIsFocusPressed) { + mIsFocusPressed = false; + } + if (down) { + mIsLongPress = false; + + KeyEvent newEvent = new KeyEvent(event.getDownTime(), event.getEventTime(), + event.getAction(), keyCode, 0); + Message msg = mHandler.obtainMessage(MSG_CAMERA_LONG_PRESS, newEvent); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, ViewConfiguration.getLongPressTimeout()); + // Consume key down events of all presses. + break; + } else { + mHandler.removeMessages(MSG_CAMERA_LONG_PRESS); + // Consume key up events of long presses only. + if (mIsLongPress && mCameraLaunch) { + Intent intent; + if (keyguardActive) { + intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); + } else { + intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); + } + isWakeKey = true; + startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); + } + } + break; + case KeyEvent.KEYCODE_ENDCALL: { result &= ~ACTION_PASS_TO_USER; if (down) { @@ -4526,6 +4603,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mWakeOnAssistKeyPress; case KeyEvent.KEYCODE_APP_SWITCH: return mWakeOnAppSwitchKeyPress; + case KeyEvent.KEYCODE_CAMERA: + case KeyEvent.KEYCODE_FOCUS: + return mWakeOnCameraKeyPress; } return true; } @@ -4577,6 +4657,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_APP_SWITCH: return mWakeOnAppSwitchKeyPress; + + case KeyEvent.KEYCODE_CAMERA: + case KeyEvent.KEYCODE_FOCUS: + return mWakeOnCameraKeyPress; } return true; @@ -5157,6 +5241,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { } catch (RemoteException unhandled) { } } + + if (mFocusReleasedGoToSleep) { + mFocusReleasedGoToSleep = false; + mPowerManager.goToSleep(SystemClock.uptimeMillis()); + } } private void handleHideBootMessage() {