331 lines
13 KiB
Java
331 lines
13 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2008 The Android Open Source 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.
|
||
|
*/
|
||
|
|
||
|
package com.android.internal.policy;
|
||
|
|
||
|
import android.app.KeyguardManager;
|
||
|
import android.app.SearchManager;
|
||
|
import android.compat.annotation.UnsupportedAppUsage;
|
||
|
import android.content.ActivityNotFoundException;
|
||
|
import android.content.Context;
|
||
|
import android.content.Intent;
|
||
|
import android.content.res.Configuration;
|
||
|
import android.media.AudioManager;
|
||
|
import android.media.session.MediaSessionManager;
|
||
|
import android.os.UserHandle;
|
||
|
import android.provider.Settings;
|
||
|
import android.telephony.TelephonyManager;
|
||
|
import android.util.Log;
|
||
|
import android.view.FallbackEventHandler;
|
||
|
import android.view.HapticFeedbackConstants;
|
||
|
import android.view.KeyEvent;
|
||
|
import android.view.View;
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public class PhoneFallbackEventHandler implements FallbackEventHandler {
|
||
|
private static String TAG = "PhoneFallbackEventHandler";
|
||
|
private static final boolean DEBUG = false;
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
Context mContext;
|
||
|
@UnsupportedAppUsage
|
||
|
View mView;
|
||
|
|
||
|
AudioManager mAudioManager;
|
||
|
KeyguardManager mKeyguardManager;
|
||
|
SearchManager mSearchManager;
|
||
|
TelephonyManager mTelephonyManager;
|
||
|
MediaSessionManager mMediaSessionManager;
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
public PhoneFallbackEventHandler(Context context) {
|
||
|
mContext = context;
|
||
|
}
|
||
|
|
||
|
public void setView(View v) {
|
||
|
mView = v;
|
||
|
}
|
||
|
|
||
|
public void preDispatchKeyEvent(KeyEvent event) {
|
||
|
getAudioManager().preDispatchKeyEvent(event, AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||
|
}
|
||
|
|
||
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||
|
|
||
|
final int action = event.getAction();
|
||
|
final int keyCode = event.getKeyCode();
|
||
|
|
||
|
if (action == KeyEvent.ACTION_DOWN) {
|
||
|
return onKeyDown(keyCode, event);
|
||
|
} else {
|
||
|
return onKeyUp(keyCode, event);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
boolean onKeyDown(int keyCode, KeyEvent event) {
|
||
|
/* ****************************************************************************
|
||
|
* HOW TO DECIDE WHERE YOUR KEY HANDLING GOES.
|
||
|
* See the comment in PhoneWindow.onKeyDown
|
||
|
* ****************************************************************************/
|
||
|
final KeyEvent.DispatcherState dispatcher = mView.getKeyDispatcherState();
|
||
|
|
||
|
switch (keyCode) {
|
||
|
case KeyEvent.KEYCODE_VOLUME_UP:
|
||
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||
|
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||
|
handleVolumeKeyEvent(event);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||
|
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||
|
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||
|
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||
|
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
||
|
handleMediaKeyEvent(event);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_CALL: {
|
||
|
if (isNotInstantAppAndKeyguardRestricted(dispatcher)) {
|
||
|
break;
|
||
|
}
|
||
|
if (event.getRepeatCount() == 0) {
|
||
|
dispatcher.startTracking(event, this);
|
||
|
} else if (event.isLongPress() && dispatcher.isTracking(event)) {
|
||
|
dispatcher.performedLongPress(event);
|
||
|
if (isUserSetupComplete()) {
|
||
|
mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||
|
// launch the VoiceDialer
|
||
|
Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
|
||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||
|
try {
|
||
|
mContext.startActivity(intent);
|
||
|
} catch (ActivityNotFoundException e) {
|
||
|
startCallActivity();
|
||
|
}
|
||
|
} else {
|
||
|
Log.i(TAG, "Not starting call activity because user "
|
||
|
+ "setup is in progress.");
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_CAMERA: {
|
||
|
if (isNotInstantAppAndKeyguardRestricted(dispatcher)) {
|
||
|
break;
|
||
|
}
|
||
|
if (event.getRepeatCount() == 0) {
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_SEARCH: {
|
||
|
if (isNotInstantAppAndKeyguardRestricted(dispatcher)) {
|
||
|
break;
|
||
|
}
|
||
|
if (event.getRepeatCount() == 0) {
|
||
|
dispatcher.startTracking(event, this);
|
||
|
} else if (event.isLongPress() && dispatcher.isTracking(event)) {
|
||
|
Configuration config = mContext.getResources().getConfiguration();
|
||
|
if (config.keyboard == Configuration.KEYBOARD_NOKEYS
|
||
|
|| config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
|
||
|
if (isUserSetupComplete()) {
|
||
|
// launch the search activity
|
||
|
Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
|
||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||
|
try {
|
||
|
mView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||
|
getSearchManager().stopSearch();
|
||
|
mContext.startActivity(intent);
|
||
|
// Only clear this if we successfully start the
|
||
|
// activity; otherwise we will allow the normal short
|
||
|
// press action to be performed.
|
||
|
dispatcher.performedLongPress(event);
|
||
|
return true;
|
||
|
} catch (ActivityNotFoundException e) {
|
||
|
// Ignore
|
||
|
}
|
||
|
} else {
|
||
|
Log.i(TAG, "Not dispatching SEARCH long press because user "
|
||
|
+ "setup is in progress.");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private boolean isNotInstantAppAndKeyguardRestricted(KeyEvent.DispatcherState dispatcher) {
|
||
|
return !mContext.getPackageManager().isInstantApp()
|
||
|
&& (getKeyguardManager().inKeyguardRestrictedInputMode() || dispatcher == null);
|
||
|
}
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
boolean onKeyUp(int keyCode, KeyEvent event) {
|
||
|
if (DEBUG) {
|
||
|
Log.d(TAG, "up " + keyCode);
|
||
|
}
|
||
|
final KeyEvent.DispatcherState dispatcher = mView.getKeyDispatcherState();
|
||
|
if (dispatcher != null) {
|
||
|
dispatcher.handleUpEvent(event);
|
||
|
}
|
||
|
|
||
|
switch (keyCode) {
|
||
|
case KeyEvent.KEYCODE_VOLUME_UP:
|
||
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||
|
case KeyEvent.KEYCODE_VOLUME_MUTE: {
|
||
|
if (!event.isCanceled()) {
|
||
|
handleVolumeKeyEvent(event);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||
|
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||
|
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||
|
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||
|
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||
|
case KeyEvent.KEYCODE_MEDIA_RECORD:
|
||
|
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||
|
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
|
||
|
handleMediaKeyEvent(event);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_CAMERA: {
|
||
|
if (isNotInstantAppAndKeyguardRestricted(dispatcher)) {
|
||
|
break;
|
||
|
}
|
||
|
if (event.isTracking() && !event.isCanceled()) {
|
||
|
// Add short press behavior here if desired
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
case KeyEvent.KEYCODE_CALL: {
|
||
|
if (isNotInstantAppAndKeyguardRestricted(dispatcher)) {
|
||
|
break;
|
||
|
}
|
||
|
if (event.isTracking() && !event.isCanceled()) {
|
||
|
if (isUserSetupComplete()) {
|
||
|
startCallActivity();
|
||
|
} else {
|
||
|
Log.i(TAG, "Not starting call activity because user "
|
||
|
+ "setup is in progress.");
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@UnsupportedAppUsage
|
||
|
void startCallActivity() {
|
||
|
Intent intent = new Intent(Intent.ACTION_CALL_BUTTON);
|
||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||
|
try {
|
||
|
mContext.startActivity(intent);
|
||
|
} catch (ActivityNotFoundException e) {
|
||
|
Log.w(TAG, "No activity found for android.intent.action.CALL_BUTTON.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SearchManager getSearchManager() {
|
||
|
if (mSearchManager == null) {
|
||
|
mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
|
||
|
}
|
||
|
return mSearchManager;
|
||
|
}
|
||
|
|
||
|
TelephonyManager getTelephonyManager() {
|
||
|
if (mTelephonyManager == null) {
|
||
|
mTelephonyManager = (TelephonyManager)mContext.getSystemService(
|
||
|
Context.TELEPHONY_SERVICE);
|
||
|
}
|
||
|
return mTelephonyManager;
|
||
|
}
|
||
|
|
||
|
KeyguardManager getKeyguardManager() {
|
||
|
if (mKeyguardManager == null) {
|
||
|
mKeyguardManager = (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
|
||
|
}
|
||
|
return mKeyguardManager;
|
||
|
}
|
||
|
|
||
|
AudioManager getAudioManager() {
|
||
|
if (mAudioManager == null) {
|
||
|
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
|
||
|
}
|
||
|
return mAudioManager;
|
||
|
}
|
||
|
|
||
|
MediaSessionManager getMediaSessionManager() {
|
||
|
if (mMediaSessionManager == null) {
|
||
|
mMediaSessionManager =
|
||
|
(MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
|
||
|
}
|
||
|
return mMediaSessionManager;
|
||
|
}
|
||
|
|
||
|
private void handleVolumeKeyEvent(KeyEvent keyEvent) {
|
||
|
getMediaSessionManager().dispatchVolumeKeyEventAsSystemService(keyEvent,
|
||
|
AudioManager.USE_DEFAULT_STREAM_TYPE);
|
||
|
}
|
||
|
|
||
|
private void handleMediaKeyEvent(KeyEvent keyEvent) {
|
||
|
getMediaSessionManager().dispatchMediaKeyEventAsSystemService(keyEvent);
|
||
|
}
|
||
|
|
||
|
private boolean isUserSetupComplete() {
|
||
|
return Settings.Secure.getInt(mContext.getContentResolver(),
|
||
|
Settings.Secure.USER_SETUP_COMPLETE, 0) != 0;
|
||
|
}
|
||
|
}
|
||
|
|