ShortcutManager.java revision 6b53e8daa69cba1a2a5a7c95a01e37ce9c53226c
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
17package com.android.internal.policy.impl;
18
19import android.content.Context;
20import android.content.Intent;
21import android.database.ContentObserver;
22import android.database.Cursor;
23import android.os.Handler;
24import android.provider.Settings;
25import android.util.Log;
26import android.util.SparseArray;
27import android.view.KeyCharacterMap;
28
29import 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 */
36class 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 keyCode The keycode of the key pushed.
104     * @param modifiers The modifiers without any that are used for chording
105     *            to invoke a shortcut.
106     * @return The intent that matches the shortcut, or null if not found.
107     */
108    public Intent getIntent(int keyCode, int modifiers) {
109        KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
110        // First try the exact keycode (with modifiers)
111        int shortcut = kcm.get(keyCode, modifiers);
112        Intent intent = shortcut != 0 ? mShortcutIntents.get(shortcut) : null;
113        if (intent != null) return intent;
114
115        // Next try the keycode without modifiers (the primary character on that key)
116        shortcut = Character.toLowerCase(kcm.get(keyCode, 0));
117        return shortcut != 0 ? mShortcutIntents.get(shortcut) : null;
118    }
119
120}
121