blob: 75a1b01319b5eac841c8953e7ad4cd736ca45606 [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* 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.internal.policy.impl;
import android.content.Context;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import java.net.URISyntaxException;
/**
* Manages quick launch shortcuts by:
* <li> Keeping the local copy in sync with the database (this is an observer)
* <li> Returning a shortcut-matching intent to clients
*/
class ShortcutManager extends ContentObserver {
private static final String TAG = "ShortcutManager";
private static final int COLUMN_SHORTCUT = 0;
private static final int COLUMN_INTENT = 1;
private static final String[] sProjection = new String[] {
Settings.Bookmarks.SHORTCUT, Settings.Bookmarks.INTENT
};
private Context mContext;
private Cursor mCursor;
/** Map of a shortcut to its intent. */
private SparseArray<Intent> mShortcutIntents;
public ShortcutManager(Context context, Handler handler) {
super(handler);
mContext = context;
mShortcutIntents = new SparseArray<Intent>();
}
/** Observes the provider of shortcut+intents */
public void observe() {
mCursor = mContext.getContentResolver().query(
Settings.Bookmarks.CONTENT_URI, sProjection, null, null, null);
mCursor.registerContentObserver(this);
updateShortcuts();
}
@Override
public void onChange(boolean selfChange) {
updateShortcuts();
}
private void updateShortcuts() {
Cursor c = mCursor;
if (!c.requery()) {
Log.e(TAG, "ShortcutObserver could not re-query shortcuts.");
return;
}
mShortcutIntents.clear();
while (c.moveToNext()) {
int shortcut = c.getInt(COLUMN_SHORTCUT);
if (shortcut == 0) continue;
String intentURI = c.getString(COLUMN_INTENT);
Intent intent = null;
try {
intent = Intent.getIntent(intentURI);
} catch (URISyntaxException e) {
Log.w(TAG, "Intent URI for shortcut invalid.", e);
}
if (intent == null) continue;
mShortcutIntents.put(shortcut, intent);
}
}
/**
* Gets the shortcut intent for a given keycode+modifier. Make sure you
* strip whatever modifier is used for invoking shortcuts (for example,
* if 'Sym+A' should invoke a shortcut on 'A', you should strip the
* 'Sym' bit from the modifiers before calling this method.
* <p>
* This will first try an exact match (with modifiers), and then try a
* match without modifiers (primary character on a key).
*
* @param kcm The key character map of the device on which the key was pressed.
* @param keyCode The key code.
* @param metaState The meta state, omitting any modifiers that were used
* to invoke the shortcut.
* @return The intent that matches the shortcut, or null if not found.
*/
public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
Intent intent = null;
// First try the exact keycode (with modifiers).
int shortcut = kcm.get(keyCode, metaState);
if (shortcut != 0) {
intent = mShortcutIntents.get(shortcut);
}
// Next try the primary character on that key.
if (intent == null) {
shortcut = Character.toLowerCase(kcm.getDisplayLabel(keyCode));
if (shortcut != 0) {
intent = mShortcutIntents.get(shortcut);
}
}
return intent;
}
}