1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.policy.impl; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.database.ContentObserver; 22 import android.database.Cursor; 23 import android.os.Handler; 24 import android.provider.Settings; 25 import android.util.Log; 26 import android.util.SparseArray; 27 import android.view.KeyCharacterMap; 28 import android.view.KeyEvent; 29 30 import java.net.URISyntaxException; 31 32 /** 33 * Manages quick launch shortcuts by: 34 * <li> Keeping the local copy in sync with the database (this is an observer) 35 * <li> Returning a shortcut-matching intent to clients 36 */ 37 class ShortcutManager extends ContentObserver { 38 39 private static final String TAG = "ShortcutManager"; 40 41 private static final int COLUMN_SHORTCUT = 0; 42 private static final int COLUMN_INTENT = 1; 43 private static final String[] sProjection = new String[] { 44 Settings.Bookmarks.SHORTCUT, Settings.Bookmarks.INTENT 45 }; 46 47 private Context mContext; 48 private Cursor mCursor; 49 /** Map of a shortcut to its intent. */ 50 private SparseArray<Intent> mShortcutIntents; 51 52 public ShortcutManager(Context context, Handler handler) { 53 super(handler); 54 55 mContext = context; 56 mShortcutIntents = new SparseArray<Intent>(); 57 } 58 59 /** Observes the provider of shortcut+intents */ 60 public void observe() { 61 mCursor = mContext.getContentResolver().query( 62 Settings.Bookmarks.CONTENT_URI, sProjection, null, null, null); 63 mCursor.registerContentObserver(this); 64 updateShortcuts(); 65 } 66 67 @Override 68 public void onChange(boolean selfChange) { 69 updateShortcuts(); 70 } 71 72 private void updateShortcuts() { 73 Cursor c = mCursor; 74 if (!c.requery()) { 75 Log.e(TAG, "ShortcutObserver could not re-query shortcuts."); 76 return; 77 } 78 79 mShortcutIntents.clear(); 80 while (c.moveToNext()) { 81 int shortcut = c.getInt(COLUMN_SHORTCUT); 82 if (shortcut == 0) continue; 83 String intentURI = c.getString(COLUMN_INTENT); 84 Intent intent = null; 85 try { 86 intent = Intent.getIntent(intentURI); 87 } catch (URISyntaxException e) { 88 Log.w(TAG, "Intent URI for shortcut invalid.", e); 89 } 90 if (intent == null) continue; 91 mShortcutIntents.put(shortcut, intent); 92 } 93 } 94 95 /** 96 * Gets the shortcut intent for a given keycode+modifier. Make sure you 97 * strip whatever modifier is used for invoking shortcuts (for example, 98 * if 'Sym+A' should invoke a shortcut on 'A', you should strip the 99 * 'Sym' bit from the modifiers before calling this method. 100 * <p> 101 * This will first try an exact match (with modifiers), and then try a 102 * match without modifiers (primary character on a key). 103 * 104 * @param kcm The key character map of the device on which the key was pressed. 105 * @param keyCode The key code. 106 * @param metaState The meta state, omitting any modifiers that were used 107 * to invoke the shortcut. 108 * @return The intent that matches the shortcut, or null if not found. 109 */ 110 public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) { 111 Intent intent = null; 112 113 // First try the exact keycode (with modifiers). 114 int shortcut = kcm.get(keyCode, metaState); 115 if (shortcut != 0) { 116 intent = mShortcutIntents.get(shortcut); 117 } 118 119 // Next try the primary character on that key. 120 if (intent == null) { 121 shortcut = Character.toLowerCase(kcm.getDisplayLabel(keyCode)); 122 if (shortcut != 0) { 123 intent = mShortcutIntents.get(shortcut); 124 } 125 } 126 127 return intent; 128 } 129 130 } 131