GlobalKeyManager.java revision d7c0c2ee45dd5367ac7863517de2e385fbd424f3
1/* 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package com.android.internal.policy.impl; 17 18import android.content.ComponentName; 19import android.content.Context; 20import android.content.Intent; 21import android.content.res.Resources; 22import android.content.res.XmlResourceParser; 23import android.os.UserHandle; 24import android.util.Log; 25import android.util.SparseArray; 26import android.view.KeyEvent; 27 28import com.android.internal.util.XmlUtils; 29 30import org.xmlpull.v1.XmlPullParserException; 31 32import java.io.IOException; 33import java.io.PrintWriter; 34 35/** 36 * Stores a mapping of global keys. 37 * <p> 38 * A global key will NOT go to the foreground application and instead only ever be sent via targeted 39 * broadcast to the specified component. The action of the intent will be 40 * {@link Intent#ACTION_GLOBAL_BUTTON} and the KeyEvent will be included in the intent with 41 * {@link Intent#EXTRA_KEY_EVENT}. 42 */ 43final class GlobalKeyManager { 44 45 private static final String TAG = "GlobalKeyManager"; 46 47 private static final String TAG_GLOBAL_KEYS = "global_keys"; 48 private static final String ATTR_VERSION = "version"; 49 private static final String TAG_KEY = "key"; 50 private static final String ATTR_KEY_CODE = "keyCode"; 51 private static final String ATTR_COMPONENT = "component"; 52 53 private static final int GLOBAL_KEY_FILE_VERSION = 1; 54 55 private SparseArray<ComponentName> mKeyMapping; 56 57 public GlobalKeyManager(Context context) { 58 mKeyMapping = new SparseArray<ComponentName>(); 59 loadGlobalKeys(context); 60 } 61 62 /** 63 * Broadcasts an intent if the keycode is part of the global key mapping. 64 * 65 * @param context context used to broadcast the event 66 * @param keyCode keyCode which triggered this function 67 * @param event keyEvent which trigged this function 68 * @return {@code true} if this was handled 69 */ 70 boolean handleGlobalKey(Context context, int keyCode, KeyEvent event) { 71 if (mKeyMapping.size() > 0) { 72 ComponentName component = mKeyMapping.get(keyCode); 73 if (component != null) { 74 Intent intent = new Intent(Intent.ACTION_GLOBAL_BUTTON) 75 .setComponent(component) 76 .putExtra(Intent.EXTRA_KEY_EVENT, event); 77 context.sendBroadcastAsUser(intent, UserHandle.CURRENT, null); 78 return true; 79 } 80 } 81 return false; 82 } 83 84 /** 85 * Returns {@code true} if the key will be handled globally. 86 */ 87 boolean shouldHandleGlobalKey(int keyCode, KeyEvent event) { 88 return mKeyMapping.get(keyCode) != null; 89 } 90 91 private void loadGlobalKeys(Context context) { 92 XmlResourceParser parser = null; 93 try { 94 parser = context.getResources().getXml(com.android.internal.R.xml.global_keys); 95 XmlUtils.beginDocument(parser, TAG_GLOBAL_KEYS); 96 int version = parser.getAttributeIntValue(null, ATTR_VERSION, 0); 97 if (GLOBAL_KEY_FILE_VERSION == version) { 98 while (true) { 99 XmlUtils.nextElement(parser); 100 String element = parser.getName(); 101 if (element == null) { 102 break; 103 } 104 if (TAG_KEY.equals(element)) { 105 String keyCodeName = parser.getAttributeValue(null, ATTR_KEY_CODE); 106 String componentName = parser.getAttributeValue(null, ATTR_COMPONENT); 107 int keyCode = KeyEvent.keyCodeFromString(keyCodeName); 108 if (keyCode != KeyEvent.KEYCODE_UNKNOWN) { 109 mKeyMapping.put(keyCode, ComponentName.unflattenFromString( 110 componentName)); 111 } 112 } 113 } 114 } 115 } catch (Resources.NotFoundException e) { 116 Log.w(TAG, "global keys file not found", e); 117 } catch (XmlPullParserException e) { 118 Log.w(TAG, "XML parser exception reading global keys file", e); 119 } catch (IOException e) { 120 Log.w(TAG, "I/O exception reading global keys file", e); 121 } finally { 122 if (parser != null) { 123 parser.close(); 124 } 125 } 126 } 127 128 public void dump(String prefix, PrintWriter pw) { 129 final int numKeys = mKeyMapping.size(); 130 if (numKeys == 0) { 131 pw.print(prefix); pw.println("mKeyMapping.size=0"); 132 return; 133 } 134 pw.print(prefix); pw.println("mKeyMapping={"); 135 for (int i = 0; i < numKeys; ++i) { 136 pw.print(" "); 137 pw.print(prefix); 138 pw.print(KeyEvent.keyCodeToString(mKeyMapping.keyAt(i))); 139 pw.print("="); 140 pw.println(mKeyMapping.valueAt(i).flattenToString()); 141 } 142 pw.print(prefix); pw.println("}"); 143 } 144} 145