/*
|
*
|
* 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.server.policy;
|
|
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;
|
import java.io.PrintWriter;
|
|
/**
|
* 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)
|
.setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
|
.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();
|
}
|
}
|
}
|
|
public void dump(String prefix, PrintWriter pw) {
|
final int numKeys = mKeyMapping.size();
|
if (numKeys == 0) {
|
pw.print(prefix); pw.println("mKeyMapping.size=0");
|
return;
|
}
|
pw.print(prefix); pw.println("mKeyMapping={");
|
for (int i = 0; i < numKeys; ++i) {
|
pw.print(" ");
|
pw.print(prefix);
|
pw.print(KeyEvent.keyCodeToString(mKeyMapping.keyAt(i)));
|
pw.print("=");
|
pw.println(mKeyMapping.valueAt(i).flattenToString());
|
}
|
pw.print(prefix); pw.println("}");
|
}
|
}
|