Merge "Add global key configuration file" into jb-mr2-dev
This commit is contained in:
@ -2578,6 +2578,14 @@ public class Intent implements Parcelable, Cloneable {
|
|||||||
public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
|
public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
|
||||||
"android.intent.action.SHOW_BRIGHTNESS_DIALOG";
|
"android.intent.action.SHOW_BRIGHTNESS_DIALOG";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast Action: A global button was pressed. Includes a single
|
||||||
|
* extra field, {@link #EXTRA_KEY_EVENT}, containing the key event that
|
||||||
|
* caused the broadcast.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Standard intent categories (see addCategory()).
|
// Standard intent categories (see addCategory()).
|
||||||
|
@ -1142,6 +1142,7 @@
|
|||||||
<java-symbol type="xml" name="time_zones_by_country" />
|
<java-symbol type="xml" name="time_zones_by_country" />
|
||||||
<java-symbol type="xml" name="sms_short_codes" />
|
<java-symbol type="xml" name="sms_short_codes" />
|
||||||
<java-symbol type="xml" name="audio_assets" />
|
<java-symbol type="xml" name="audio_assets" />
|
||||||
|
<java-symbol type="xml" name="global_keys" />
|
||||||
|
|
||||||
<java-symbol type="raw" name="accessibility_gestures" />
|
<java-symbol type="raw" name="accessibility_gestures" />
|
||||||
<java-symbol type="raw" name="incognito_mode_start_page" />
|
<java-symbol type="raw" name="incognito_mode_start_page" />
|
||||||
|
31
core/res/res/xml/global_keys.xml
Normal file
31
core/res/res/xml/global_keys.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
** Copyright 2013, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Mapping of keycodes to components which will be handled globally.
|
||||||
|
Modify this file to add global keys.
|
||||||
|
A global key will NOT go to the foreground application and instead only ever be sent via targeted
|
||||||
|
broadcast to the specified component. The action of the intent will be
|
||||||
|
android.intent.action.GLOBAL_BUTTON and the KeyEvent will be included in the intent as
|
||||||
|
android.intent.extra.KEY_EVENT.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<global_keys version="1">
|
||||||
|
<!-- Example format: keyCode = keycode to handle globally. component = component which will handle this key. -->
|
||||||
|
<!-- <key keyCode="KEYCODE_VOLUME_UP" component="com.android.example.keys/.VolumeKeyHandler" /> -->
|
||||||
|
</global_keys>
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* 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.impl;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.XmlResourceParser;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
|
import com.android.internal.util.XmlUtils;
|
||||||
|
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a mapping of global keys.
|
||||||
|
* <p>
|
||||||
|
* A global key will NOT go to the foreground application and instead only ever be sent via targeted
|
||||||
|
* broadcast to the specified component. The action of the intent will be
|
||||||
|
* {@link Intent#ACTION_GLOBAL_BUTTON} and the KeyEvent will be included in the intent with
|
||||||
|
* {@link Intent#EXTRA_KEY_EVENT}.
|
||||||
|
*/
|
||||||
|
final class GlobalKeyManager {
|
||||||
|
|
||||||
|
private static final String TAG = "GlobalKeyManager";
|
||||||
|
|
||||||
|
private static final String TAG_GLOBAL_KEYS = "global_keys";
|
||||||
|
private static final String ATTR_VERSION = "version";
|
||||||
|
private static final String TAG_KEY = "key";
|
||||||
|
private static final String ATTR_KEY_CODE = "keyCode";
|
||||||
|
private static final String ATTR_COMPONENT = "component";
|
||||||
|
|
||||||
|
private static final int GLOBAL_KEY_FILE_VERSION = 1;
|
||||||
|
|
||||||
|
private SparseArray<ComponentName> mKeyMapping;
|
||||||
|
|
||||||
|
public GlobalKeyManager(Context context) {
|
||||||
|
mKeyMapping = new SparseArray<ComponentName>();
|
||||||
|
loadGlobalKeys(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts an intent if the keycode is part of the global key mapping.
|
||||||
|
*
|
||||||
|
* @param context context used to broadcast the event
|
||||||
|
* @param keyCode keyCode which triggered this function
|
||||||
|
* @param event keyEvent which trigged this function
|
||||||
|
* @return {@code true} if this was handled
|
||||||
|
*/
|
||||||
|
boolean handleGlobalKey(Context context, int keyCode, KeyEvent event) {
|
||||||
|
if (mKeyMapping.size() > 0) {
|
||||||
|
ComponentName component = mKeyMapping.get(keyCode);
|
||||||
|
if (component != null) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GLOBAL_BUTTON)
|
||||||
|
.setComponent(component)
|
||||||
|
.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
||||||
|
context.sendBroadcastAsUser(intent, UserHandle.CURRENT, null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns {@code true} if the key will be handled globally.
|
||||||
|
*/
|
||||||
|
boolean shouldHandleGlobalKey(int keyCode, KeyEvent event) {
|
||||||
|
return mKeyMapping.get(keyCode) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadGlobalKeys(Context context) {
|
||||||
|
XmlResourceParser parser = null;
|
||||||
|
try {
|
||||||
|
parser = context.getResources().getXml(com.android.internal.R.xml.global_keys);
|
||||||
|
XmlUtils.beginDocument(parser, TAG_GLOBAL_KEYS);
|
||||||
|
int version = parser.getAttributeIntValue(null, ATTR_VERSION, 0);
|
||||||
|
if (GLOBAL_KEY_FILE_VERSION == version) {
|
||||||
|
while (true) {
|
||||||
|
XmlUtils.nextElement(parser);
|
||||||
|
String element = parser.getName();
|
||||||
|
if (element == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (TAG_KEY.equals(element)) {
|
||||||
|
String keyCodeName = parser.getAttributeValue(null, ATTR_KEY_CODE);
|
||||||
|
String componentName = parser.getAttributeValue(null, ATTR_COMPONENT);
|
||||||
|
int keyCode = KeyEvent.keyCodeFromString(keyCodeName);
|
||||||
|
if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
|
||||||
|
mKeyMapping.put(keyCode, ComponentName.unflattenFromString(
|
||||||
|
componentName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Resources.NotFoundException e) {
|
||||||
|
Log.w(TAG, "global keys file not found", e);
|
||||||
|
} catch (XmlPullParserException e) {
|
||||||
|
Log.w(TAG, "XML parser exception reading global keys file", e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "I/O exception reading global keys file", e);
|
||||||
|
} finally {
|
||||||
|
if (parser != null) {
|
||||||
|
parser.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -441,6 +441,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
PowerManager.WakeLock mBroadcastWakeLock;
|
PowerManager.WakeLock mBroadcastWakeLock;
|
||||||
boolean mHavePendingMediaKeyRepeatWithWakeLock;
|
boolean mHavePendingMediaKeyRepeatWithWakeLock;
|
||||||
|
|
||||||
|
// Maps global key codes to the components that will handle them.
|
||||||
|
private GlobalKeyManager mGlobalKeyManager;
|
||||||
|
|
||||||
// Fallback actions by key code.
|
// Fallback actions by key code.
|
||||||
private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
|
private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
|
||||||
new SparseArray<KeyCharacterMap.FallbackAction>();
|
new SparseArray<KeyCharacterMap.FallbackAction>();
|
||||||
@ -898,6 +901,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
mScreenshotChordEnabled = mContext.getResources().getBoolean(
|
mScreenshotChordEnabled = mContext.getResources().getBoolean(
|
||||||
com.android.internal.R.bool.config_enableScreenshotChord);
|
com.android.internal.R.bool.config_enableScreenshotChord);
|
||||||
|
|
||||||
|
mGlobalKeyManager = new GlobalKeyManager(mContext);
|
||||||
|
|
||||||
// Controls rotation and the like.
|
// Controls rotation and the like.
|
||||||
initializeHdmiState();
|
initializeHdmiState();
|
||||||
|
|
||||||
@ -2140,6 +2145,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Let the application handle the key.
|
// Let the application handle the key.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3585,6 +3594,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the key would be handled globally, just return the result, don't worry about special
|
||||||
|
// key processing.
|
||||||
|
if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle special keys.
|
// Handle special keys.
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||||
|
Reference in New Issue
Block a user