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 29 import java.net.URISyntaxException; 30 31 /** 32 * Manages quick launch shortcuts by: 33 * <li> Keeping the local copy in sync with the database (this is an observer) 34 * <li> Returning a shortcut-matching intent to clients 35 */ 36 class ShortcutManager extends ContentObserver { 37 38 private static final String TAG = "ShortcutManager"; 39 40 private static final int COLUMN_SHORTCUT = 0; 41 private static final int COLUMN_INTENT = 1; 42 private static final String[] sProjection = new String[] { 43 Settings.Bookmarks.SHORTCUT, Settings.Bookmarks.INTENT 44 }; 45 46 private Context mContext; 47 private Cursor mCursor; 48 /** Map of a shortcut to its intent. */ 49 private SparseArray<Intent> mShortcutIntents; 50 51 public ShortcutManager(Context context, Handler handler) { 52 super(handler); 53 54 mContext = context; 55 mShortcutIntents = new SparseArray<Intent>(); 56 } 57 58 /** Observes the provider of shortcut+intents */ 59 public void observe() { 60 mCursor = mContext.getContentResolver().query( 61 Settings.Bookmarks.CONTENT_URI, sProjection, null, null, null); 62 mCursor.registerContentObserver(this); 63 updateShortcuts(); 64 } 65 66 @Override 67 public void onChange(boolean selfChange) { 68 updateShortcuts(); 69 } 70 71 private void updateShortcuts() { 72 Cursor c = mCursor; 73 if (!c.requery()) { 74 Log.e(TAG, "ShortcutObserver could not re-query shortcuts."); 75 return; 76 } 77 78 mShortcutIntents.clear(); 79 while (c.moveToNext()) { 80 int shortcut = c.getInt(COLUMN_SHORTCUT); 81 if (shortcut == 0) continue; 82 String intentURI = c.getString(COLUMN_INTENT); 83 Intent intent = null; 84 try { 85 intent = Intent.getIntent(intentURI); 86 } catch (URISyntaxException e) { 87 Log.w(TAG, "Intent URI for shortcut invalid.", e); 88 } 89 if (intent == null) continue; 90 mShortcutIntents.put(shortcut, intent); 91 } 92 } 93 94 /** 95 * Gets the shortcut intent for a given keycode+modifier. Make sure you 96 * strip whatever modifier is used for invoking shortcuts (for example, 97 * if 'Sym+A' should invoke a shortcut on 'A', you should strip the 98 * 'Sym' bit from the modifiers before calling this method. 99 * <p> 100 * This will first try an exact match (with modifiers), and then try a 101 * match without modifiers (primary character on a key). 102 * 103 * @param kcm The key character map of the device on which the key was pressed. 104 * @param keyCode The key code. 105 * @param metaState The meta state, omitting any modifiers that were used 106 * to invoke the shortcut. 107 * @return The intent that matches the shortcut, or null if not found. 108 */ 109 public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) { 110 Intent intent = null; 111 112 // First try the exact keycode (with modifiers). 113 int shortcut = kcm.get(keyCode, metaState); 114 if (shortcut != 0) { 115 intent = mShortcutIntents.get(shortcut); 116 } 117 118 // Next try the primary character on that key. 119 if (intent == null) { 120 shortcut = Character.toLowerCase(kcm.getDisplayLabel(keyCode)); 121 if (shortcut != 0) { 122 intent = mShortcutIntents.get(shortcut); 123 } 124 } 125 126 return intent; 127 } 128 129 } 130