summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt25
-rw-r--r--api/system-current.txt25
-rw-r--r--api/test-current.txt25
-rw-r--r--core/java/android/app/Activity.java42
-rw-r--r--core/java/android/app/Dialog.java14
-rw-r--r--core/java/android/service/dreams/DreamService.java19
-rw-r--r--core/java/android/view/IWindow.aidl7
-rw-r--r--core/java/android/view/IWindowManager.aidl8
-rw-r--r--core/java/android/view/KeyboardShortcutGroup.java102
-rw-r--r--core/java/android/view/KeyboardShortcutInfo.java134
-rw-r--r--core/java/android/view/View.java12
-rw-r--r--core/java/android/view/ViewRootImpl.java33
-rw-r--r--core/java/android/view/Window.java11
-rw-r--r--core/java/android/view/WindowCallbackWrapper.java7
-rw-r--r--core/java/android/view/WindowManager.java30
-rw-r--r--core/java/android/view/WindowManagerImpl.java25
-rw-r--r--core/java/com/android/internal/policy/DecorView.java20
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java6
-rw-r--r--core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java6
-rw-r--r--packages/SystemUI/res/values/strings.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java88
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java9
23 files changed, 626 insertions, 36 deletions
diff --git a/api/current.txt b/api/current.txt
index 629d832c0c3c..1dcd309b16ca 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3505,6 +3505,7 @@ package android.app {
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4189,6 +4190,7 @@ package android.app {
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -33502,6 +33504,7 @@ package android.service.dreams {
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -40390,6 +40393,27 @@ package android.view {
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -42391,6 +42415,7 @@ package android.view {
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
diff --git a/api/system-current.txt b/api/system-current.txt
index 6a36ce05acca..adce4806c654 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3611,6 +3611,7 @@ package android.app {
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4310,6 +4311,7 @@ package android.app {
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -35640,6 +35642,7 @@ package android.service.dreams {
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -42741,6 +42744,27 @@ package android.view {
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -44743,6 +44767,7 @@ package android.view {
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
diff --git a/api/test-current.txt b/api/test-current.txt
index 21b101fef449..3fed63215746 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3505,6 +3505,7 @@ package android.app {
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public void onProvideAssistContent(android.app.assist.AssistContent);
method public void onProvideAssistData(android.os.Bundle);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public android.net.Uri onProvideReferrer();
method public void onRequestPermissionsResult(int, java.lang.String[], int[]);
method protected void onRestart();
@@ -4189,6 +4190,7 @@ package android.app {
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public void onRestoreInstanceState(android.os.Bundle);
method public android.os.Bundle onSaveInstanceState();
method public boolean onSearchRequested(android.view.SearchEvent);
@@ -33516,6 +33518,7 @@ package android.service.dreams {
method public boolean onMenuOpened(int, android.view.Menu);
method public void onPanelClosed(int, android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public boolean onSearchRequested(android.view.SearchEvent);
method public boolean onSearchRequested();
method public void onWakeUp();
@@ -40406,6 +40409,27 @@ package android.view {
method public void startTracking(android.view.KeyEvent, java.lang.Object);
}
+ public final class KeyboardShortcutGroup implements android.os.Parcelable {
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence, java.util.List<android.view.KeyboardShortcutInfo>);
+ ctor public KeyboardShortcutGroup(java.lang.CharSequence);
+ method public void addItem(android.view.KeyboardShortcutInfo);
+ method public int describeContents();
+ method public java.util.List<android.view.KeyboardShortcutInfo> getItems();
+ method public java.lang.CharSequence getLabel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutGroup> CREATOR;
+ }
+
+ public final class KeyboardShortcutInfo implements android.os.Parcelable {
+ ctor public KeyboardShortcutInfo(java.lang.CharSequence, char, int);
+ method public int describeContents();
+ method public char getBaseCharacter();
+ method public java.lang.CharSequence getLabel();
+ method public int getModifiers();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.view.KeyboardShortcutInfo> CREATOR;
+ }
+
public abstract class LayoutInflater {
ctor protected LayoutInflater(android.content.Context);
ctor protected LayoutInflater(android.view.LayoutInflater, android.content.Context);
@@ -42407,6 +42431,7 @@ package android.view {
method public abstract boolean onMenuOpened(int, android.view.Menu);
method public abstract void onPanelClosed(int, android.view.Menu);
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public abstract void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract boolean onSearchRequested(android.view.SearchEvent);
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 34527c2623c6..e31259692501 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -62,6 +62,7 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.media.AudioManager;
import android.media.session.MediaController;
import android.net.Uri;
@@ -71,6 +72,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.StrictMode;
import android.os.UserHandle;
@@ -78,23 +80,28 @@ import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
+import android.transition.Scene;
+import android.transition.TransitionManager;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SuperNotCalledException;
import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
@@ -103,10 +110,17 @@ import android.view.ViewGroup.LayoutParams;
import android.view.ViewManager;
import android.view.ViewRootImpl;
import android.view.Window;
+import android.view.Window.WindowControllerCallback;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.widget.AdapterView;
+import android.widget.Toolbar;
+
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.ToolbarActionBar;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.PhoneWindow;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -116,6 +130,8 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import static java.lang.Character.MIN_VALUE;
+
/**
* An activity is a single, focused thing that the user can do. Almost all
* activities interact with the user, so the Activity class takes care of
@@ -1594,6 +1610,30 @@ public class Activity extends ContextThemeWrapper
public void onProvideAssistContent(AssistContent outContent) {
}
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ if (menu == null) {
+ return;
+ }
+ KeyboardShortcutGroup group = null;
+ int menuSize = menu.size();
+ for (int i = 0; i < menuSize; ++i) {
+ final MenuItem item = menu.getItem(i);
+ final CharSequence title = item.getTitle();
+ final char alphaShortcut = item.getAlphabeticShortcut();
+ if (title != null && alphaShortcut != MIN_VALUE) {
+ if (group == null) {
+ group = new KeyboardShortcutGroup(null /* no label */);
+ }
+ group.addItem(new KeyboardShortcutInfo(
+ title, alphaShortcut, KeyEvent.META_CTRL_ON));
+ }
+ }
+ if (group != null) {
+ data.add(group);
+ }
+ }
+
/**
* Ask to have the current assistant shown to the user. This only works if the calling
* activity is the current foreground activity. It is the same as calling
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e8e2c44ce37..79461b4863ef 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -21,9 +21,8 @@ import android.annotation.DrawableRes;
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.NonNull;
-import android.annotation.StringRes;
-
import android.annotation.Nullable;
+import android.annotation.StringRes;
import android.annotation.StyleRes;
import android.content.ComponentName;
import android.content.Context;
@@ -44,11 +43,11 @@ import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
@@ -60,8 +59,10 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.policy.PhoneWindow;
import java.lang.ref.WeakReference;
+import java.util.List;
/**
* Base class for Dialogs.
@@ -1081,6 +1082,13 @@ public class Dialog implements DialogInterface, Window.Callback,
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ }
+
+ /**
* @return The activity associated with this dialog, or null if there is no associated activity.
*/
private ComponentName getAssociatedActivity() {
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index bb46e8302de6..816ecde84377 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -15,9 +15,6 @@
*/
package android.service.dreams;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
import android.annotation.IdRes;
import android.annotation.LayoutRes;
import android.annotation.Nullable;
@@ -33,27 +30,32 @@ import android.os.IBinder;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.MathUtils;
import android.util.Slog;
import android.view.ActionMode;
import android.view.Display;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.SearchEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
-import android.util.MathUtils;
+import com.android.internal.policy.PhoneWindow;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils.Dump;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
/**
* Extend this class to implement a custom dream (available to the user as a "Daydream").
*
@@ -365,6 +367,11 @@ public class DreamService extends Service implements Window.Callback {
@Override
public void onActionModeFinished(ActionMode mode) {
}
+
+ /** {@inheritDoc} */
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ }
// end Window.Callback methods
// begin public api
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 9e478c1d1e73..923139406088 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -25,6 +25,8 @@ import android.view.DragEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
+import com.android.internal.os.IResultReceiver;
+
/**
* API back to a client window that the Window Manager uses to inform it of
* interesting things happening.
@@ -83,4 +85,9 @@ oneway interface IWindow {
* Called for non-application windows when the enter animation has completed.
*/
void dispatchWindowShown();
+
+ /**
+ * Called when Keyboard Shortcuts are requested for the window.
+ */
+ void requestAppKeyboardShortcuts(IResultReceiver receiver);
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 84d312d59b64..b045c17a9295 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -17,6 +17,7 @@
package android.view;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -370,4 +371,11 @@ interface IWindowManager
* @param alpha The translucency of the dim layer, between 0 and 1.
*/
void setResizeDimLayer(boolean visible, int targetStackId, float alpha);
+
+ /**
+ * Requests Keyboard Shortcuts from the displayed window.
+ *
+ * @param receiver The receiver to deliver the results to.
+ */
+ void requestAppKeyboardShortcuts(IResultReceiver receiver);
}
diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java
new file mode 100644
index 000000000000..013255b9a612
--- /dev/null
+++ b/core/java/android/view/KeyboardShortcutGroup.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2015 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 android.view;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+/**
+ * A group of {@link KeyboardShortcutInfo}.
+ */
+public final class KeyboardShortcutGroup implements Parcelable {
+ private final CharSequence mLabel;
+ private final List<KeyboardShortcutInfo> mItems;
+
+ /**
+ * @param label The title to be used for this group, or null if there is none.
+ * @param items The set of items to be included.
+ */
+ public KeyboardShortcutGroup(@Nullable CharSequence label,
+ @NonNull List<KeyboardShortcutInfo> items) {
+ mLabel = label;
+ mItems = new ArrayList<>(checkNotNull(items));
+ }
+
+ /**
+ * @param label The title to be used for this group, or null if there is none.
+ */
+ public KeyboardShortcutGroup(@Nullable CharSequence label) {
+ this(label, Collections.<KeyboardShortcutInfo>emptyList());
+ }
+
+ private KeyboardShortcutGroup(Parcel source) {
+ mItems = new ArrayList<>();
+ mLabel = source.readCharSequence();
+ source.readTypedList(mItems, KeyboardShortcutInfo.CREATOR);
+ }
+
+ /**
+ * Returns the label to be used to describe this group.
+ */
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Returns the list of items included in this group.
+ */
+ public List<KeyboardShortcutInfo> getItems() {
+ return mItems;
+ }
+
+ /**
+ * Adds an item to the existing list.
+ *
+ * @param item The item to be added.
+ */
+ public void addItem(KeyboardShortcutInfo item) {
+ mItems.add(item);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mLabel);
+ dest.writeTypedList(mItems);
+ }
+
+ public static final Creator<KeyboardShortcutGroup> CREATOR =
+ new Creator<KeyboardShortcutGroup>() {
+ public KeyboardShortcutGroup createFromParcel(Parcel source) {
+ return new KeyboardShortcutGroup(source);
+ }
+ public KeyboardShortcutGroup[] newArray(int size) {
+ return new KeyboardShortcutGroup[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java
new file mode 100644
index 000000000000..2c9006deb189
--- /dev/null
+++ b/core/java/android/view/KeyboardShortcutInfo.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 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 android.view;
+
+import android.annotation.Nullable;
+import android.graphics.drawable.Icon;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+import static java.lang.Character.MIN_VALUE;
+
+/**
+ * Information about a Keyboard Shortcut.
+ */
+public final class KeyboardShortcutInfo implements Parcelable {
+ private final CharSequence mLabel;
+ private final Icon mIcon;
+ private final char mBaseCharacter;
+ private final int mModifiers;
+
+ /**
+ * @param label The label that identifies the action performed by this shortcut.
+ * @param icon An icon that identifies the action performed by this shortcut.
+ * @param baseCharacter The character that triggers the shortcut.
+ * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut.
+ * These should be a combination of {@link KeyEvent#META_CTRL_ON},
+ * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and
+ * {@link KeyEvent#META_ALT_ON}.
+ *
+ * @hide
+ */
+ public KeyboardShortcutInfo(
+ @Nullable CharSequence label, @Nullable Icon icon, char baseCharacter, int modifiers) {
+ mLabel = label;
+ mIcon = icon;
+ checkArgument(baseCharacter != MIN_VALUE);
+ mBaseCharacter = baseCharacter;
+ mModifiers = modifiers;
+ }
+
+ /**
+ * Convenience constructor for shortcuts with a label and no icon.
+ *
+ * @param label The label that identifies the action performed by this shortcut.
+ * @param baseCharacter The character that triggers the shortcut.
+ * @param modifiers The set of modifiers that, combined with the key, trigger the shortcut.
+ * These should be a combination of {@link KeyEvent#META_CTRL_ON},
+ * {@link KeyEvent#META_SHIFT_ON}, {@link KeyEvent#META_META_ON} and
+ * {@link KeyEvent#META_ALT_ON}.
+ */
+ public KeyboardShortcutInfo(CharSequence label, char baseCharacter, int modifiers) {
+ mLabel = label;
+ checkArgument(baseCharacter != MIN_VALUE);
+ mBaseCharacter = baseCharacter;
+ mModifiers = modifiers;
+ mIcon = null;
+ }
+
+ private KeyboardShortcutInfo(Parcel source) {
+ mLabel = source.readCharSequence();
+ mIcon = (Icon) source.readParcelable(null);
+ mBaseCharacter = (char) source.readInt();
+ mModifiers = source.readInt();
+ }
+
+ /**
+ * Returns the label to be used to describe this shortcut.
+ */
+ @Nullable
+ public CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * Returns the icon to be used to describe this shortcut.
+ *
+ * @hide
+ */
+ @Nullable
+ public Icon getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Returns the base character that, combined with the modifiers, triggers this shortcut.
+ */
+ public char getBaseCharacter() {
+ return mBaseCharacter;
+ }
+
+ /**
+ * Returns the set of modifiers that, combined with the key, trigger this shortcut.
+ */
+ public int getModifiers() {
+ return mModifiers;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequence(mLabel);
+ dest.writeParcelable(mIcon, 0);
+ dest.writeInt(mBaseCharacter);
+ dest.writeInt(mModifiers);
+ }
+
+ public static final Creator<KeyboardShortcutInfo> CREATOR =
+ new Creator<KeyboardShortcutInfo>() {
+ public KeyboardShortcutInfo createFromParcel(Parcel source) {
+ return new KeyboardShortcutInfo(source);
+ }
+ public KeyboardShortcutInfo[] newArray(int size) {
+ return new KeyboardShortcutInfo[size];
+ }
+ };
+} \ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 68f1ac3c1108..5559d4dbe705 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -79,10 +79,11 @@ import android.util.StateSet;
import android.util.SuperNotCalledException;
import android.util.TypedValue;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.AccessibilityIterators.TextSegmentIterator;
import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
-import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
+import android.view.AccessibilityIterators.TextSegmentIterator;
+import android.view.AccessibilityIterators.WordTextSegmentIterator;
+import android.view.ViewGroup.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityEventSource;
import android.view.accessibility.AccessibilityManager;
@@ -21715,6 +21716,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * @hide
+ */
+ public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> data) {
+ // Do nothing.
+ }
+
+ /**
* Interface definition for a callback to be invoked when a hardware key event is
* dispatched to this view. The callback will be invoked before the key event is
* given to the view. This is only useful for hardware keyboards; a software input
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3eb2e37be781..a14f0dcc2541 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -79,6 +79,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
import com.android.internal.R;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.PhoneFallbackEventHandler;
import com.android.internal.view.BaseSurfaceHolder;
@@ -3235,6 +3236,7 @@ public final class ViewRootImpl implements ViewParent,
private final static int MSG_WINDOW_MOVED = 23;
private final static int MSG_SYNTHESIZE_INPUT_EVENT = 24;
private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
+ private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
final class ViewRootHandler extends Handler {
@Override
@@ -3511,7 +3513,11 @@ public final class ViewRootImpl implements ViewParent,
} break;
case MSG_DISPATCH_WINDOW_SHOWN: {
handleDispatchWindowShown();
- }
+ } break;
+ case MSG_REQUEST_KEYBOARD_SHORTCUTS: {
+ IResultReceiver receiver = (IResultReceiver) msg.obj;
+ handleRequestKeyboardShortcuts(receiver);
+ } break;
}
}
}
@@ -5404,6 +5410,19 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mTreeObserver.dispatchOnWindowShown();
}
+ public void handleRequestKeyboardShortcuts(IResultReceiver receiver) {
+ Bundle data = new Bundle();
+ ArrayList<KeyboardShortcutGroup> list = new ArrayList<>();
+ if (mView != null) {
+ mView.requestKeyboardShortcuts(list);
+ }
+ data.putParcelableArrayList(WindowManager.PARCEL_KEY_SHORTCUTS_ARRAY, list);
+ try {
+ receiver.send(0, data);
+ } catch (RemoteException e) {
+ }
+ }
+
public void getLastTouchPoint(Point outLocation) {
outLocation.x = (int) mLastTouchPoint.x;
outLocation.y = (int) mLastTouchPoint.y;
@@ -6333,6 +6352,10 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ public void dispatchRequestKeyboardShortcuts(IResultReceiver receiver) {
+ mHandler.obtainMessage(MSG_REQUEST_KEYBOARD_SHORTCUTS, receiver).sendToTarget();
+ }
+
/**
* Post a callback to send a
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
@@ -6906,6 +6929,14 @@ public final class ViewRootImpl implements ViewParent,
viewAncestor.dispatchWindowShown();
}
}
+
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ ViewRootImpl viewAncestor = mViewAncestor.get();
+ if (viewAncestor != null) {
+ viewAncestor.dispatchRequestKeyboardShortcuts(receiver);
+ }
+ }
}
public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0b06d1591731..d89369bef170 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -42,6 +42,8 @@ import android.transition.Transition;
import android.transition.TransitionManager;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* Abstract base class for a top-level window look and behavior policy. An
* instance of this class should be used as the top-level view added to the
@@ -556,6 +558,15 @@ public abstract class Window {
* @param mode The mode that was just finished.
*/
public void onActionModeFinished(ActionMode mode);
+
+ /**
+ * Called when Keyboard Shortcuts are requested for the current window.
+ *
+ * @param data The data list to populate with shortcuts.
+ * @param menu The current menu, which may be null.
+ */
+ public void onProvideKeyboardShortcuts(
+ List<KeyboardShortcutGroup> data, @Nullable Menu menu);
}
/** @hide */
diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java
index 8ce1f8c7e310..bed74e95ae0a 100644
--- a/core/java/android/view/WindowCallbackWrapper.java
+++ b/core/java/android/view/WindowCallbackWrapper.java
@@ -19,6 +19,8 @@ package android.view;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* A simple decorator stub for Window.Callback that passes through any calls
* to the wrapped instance as a base implementation. Call super.foo() to call into
@@ -150,5 +152,10 @@ public class WindowCallbackWrapper implements Window.Callback {
public void onActionModeFinished(ActionMode mode) {
mWrapped.onActionModeFinished(mode);
}
+
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {
+ mWrapped.onProvideKeyboardShortcuts(data, menu);
+ }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 251f4c802ce6..772eeec880ee 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -29,6 +29,8 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
+import java.util.List;
+
/**
* The interface that apps use to talk to the window manager.
@@ -118,6 +120,34 @@ public interface WindowManager extends ViewManager {
*/
public void removeViewImmediate(View view);
+ /**
+ * Used to asynchronously request Keyboard Shortcuts from the focused window.
+ *
+ * @hide
+ */
+ public interface KeyboardShortcutsReceiver {
+ /**
+ * Callback used when the focused window keyboard shortcuts are ready to be displayed.
+ *
+ * @param result The keyboard shortcuts to be displayed.
+ */
+ void onKeyboardShortcutsReceived(List<KeyboardShortcutGroup> result);
+ }
+
+ /**
+ * @hide
+ */
+ public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
+
+ /**
+ * Request for keyboard shortcuts to be retrieved asynchronously.
+ *
+ * @param receiver The callback to be triggered when the result is ready.
+ *
+ * @hide
+ */
+ public void requestAppKeyboardShortcuts(final KeyboardShortcutsReceiver receiver);
+
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
/**
* X position for this window. With the default gravity it is ignored.
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 98e9f54c13f9..6e11671016b4 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -17,7 +17,15 @@
package android.view;
import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.R;
+
+import java.util.List;
/**
* Provides low-level communication with the system window manager for
@@ -117,6 +125,23 @@ public final class WindowManagerImpl implements WindowManager {
}
@Override
+ public void requestAppKeyboardShortcuts(final KeyboardShortcutsReceiver receiver) {
+ IResultReceiver resultReceiver = new IResultReceiver.Stub() {
+ @Override
+ public void send(int resultCode, Bundle resultData) throws RemoteException {
+ List<KeyboardShortcutGroup> result =
+ resultData.getParcelableArrayList(PARCEL_KEY_SHORTCUTS_ARRAY);
+ receiver.onKeyboardShortcutsReceived(result);
+ }
+ };
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .requestAppKeyboardShortcuts(resultReceiver);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
public Display getDefaultDisplay() {
return mDisplay;
}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index cea9867b8d88..7ae0efb6030b 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -17,6 +17,7 @@
package com.android.internal.policy;
import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow.PanelFeatureState;
import com.android.internal.policy.PhoneWindow.PhoneWindowMenuCallback;
import com.android.internal.view.FloatingActionMode;
import com.android.internal.view.RootViewSurfaceTaker;
@@ -28,6 +29,8 @@ import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.DecorCaptionView;
import com.android.internal.widget.FloatingToolbar;
+import java.util.List;
+
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
@@ -48,6 +51,7 @@ import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.InputQueue;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -85,6 +89,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATIO
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
/** @hide */
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
@@ -1956,6 +1961,21 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
res.getConfiguration().screenWidthDp, res.getDisplayMetrics());
}
+ /**
+ * @hide
+ */
+ @Override
+ public void requestKeyboardShortcuts(List<KeyboardShortcutGroup> list) {
+ final PanelFeatureState st = mWindow.getPanelState(FEATURE_OPTIONS_PANEL, false);
+ if (!mWindow.isDestroyed() && st != null && mWindow.getCallback() != null) {
+ try {
+ mWindow.getCallback().onProvideKeyboardShortcuts(list, st.menu);
+ } catch (AbstractMethodError e) {
+ // We run into this if the app is using supportlib.
+ }
+ }
+ }
+
private static class ColorViewState {
View view = null;
int targetVisibility = View.INVISIBLE;
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 8699843eb83b..aa4b564c3800 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -25,6 +25,8 @@ import android.view.DragEvent;
import android.view.IWindow;
import android.view.IWindowSession;
+import com.android.internal.os.IResultReceiver;
+
public class BaseIWindow extends IWindow.Stub {
private IWindowSession mSession;
public int mSeq;
@@ -103,4 +105,8 @@ public class BaseIWindow extends IWindow.Stub {
@Override
public void dispatchWindowShown() {
}
+
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
index 48590c1ec463..1966313a41f0 100644
--- a/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/PhoneWindowActionModeTest.java
@@ -22,6 +22,7 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.view.ActionMode;
import android.view.ActionMode.Callback;
import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -32,6 +33,8 @@ import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* Tests {@link PhoneWindow}'s {@link ActionMode} related methods.
*/
@@ -288,6 +291,9 @@ public final class PhoneWindowActionModeTest
@Override
public void onActionModeFinished(ActionMode mode) {}
+
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, Menu menu) {}
}
private static final class MockActionModeCallback implements ActionMode.Callback {
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4136c110c649..0e4f98f9c715 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1281,4 +1281,13 @@
<!-- Summary of switch for battery saver [CHAR LIMIT=NONE] -->
<string name="battery_detail_switch_summary">Reduces performance and background data</string>
+ <!-- User visible title for the system-wide keyboard shortcuts list. -->
+ <string name="keyboard_shortcut_group_system">System</string>
+ <!-- User visible title for the keyboard shortcut that takes the user to the home screen. -->
+ <string name="keyboard_shortcut_group_system_home">Home</string>
+ <!-- User visible title for the the keyboard shortcut that takes the user to the recents screen. -->
+ <string name="keyboard_shortcut_group_system_recents">Recents</string>
+ <!-- User visible title for the the keyboard shortcut that triggers the back action. -->
+ <string name="keyboard_shortcut_group_system_back">Back</string>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 3406da94e53c..f9e825aaf064 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -60,6 +60,7 @@ import android.util.Pair;
import android.view.Display;
import android.view.IDockedStackListener;
import android.view.WindowManager;
+import android.view.WindowManager.KeyboardShortcutsReceiver;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.app.AssistUtils;
@@ -915,4 +916,8 @@ public class SystemServicesProxy {
e.printStackTrace();
}
}
+
+ public void requestKeyboardShortcuts(Context context, KeyboardShortcutsReceiver receiver) {
+ mWm.requestAppKeyboardShortcuts(receiver);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 3e0ea90f7694..b36fb7e65f7e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -20,50 +20,92 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
-import android.view.Gravity;
+import android.os.Handler;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.view.WindowManager.KeyboardShortcutsReceiver;
import com.android.systemui.R;
+import com.android.systemui.recents.Recents;
+
+import java.util.List;
+
+import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.graphics.Color.TRANSPARENT;
+import static android.view.Gravity.TOP;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
/**
* Contains functionality for handling keyboard shortcuts.
*/
public class KeyboardShortcuts {
+ private static final String TAG = "KeyboardShortcuts";
+
private Dialog mKeyboardShortcutsDialog;
public KeyboardShortcuts() {}
- public void toggleKeyboardShortcuts(Context context) {
+ public void toggleKeyboardShortcuts(final Context context) {
if (mKeyboardShortcutsDialog == null) {
- // Create dialog.
- AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
- LayoutInflater inflater = (LayoutInflater) context.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- final View keyboardShortcutsView = inflater.inflate(
- R.layout.keyboard_shortcuts_view, null);
-
- populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
- R.id.keyboard_shortcuts_wrapper));
- dialogBuilder.setView(keyboardShortcutsView);
- mKeyboardShortcutsDialog = dialogBuilder.create();
- mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
-
- // Setup window.
- Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
- keyboardShortcutsWindow.setType(
- WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
- keyboardShortcutsWindow.setBackgroundDrawable(
- new ColorDrawable(android.graphics.Color.TRANSPARENT));
- keyboardShortcutsWindow.setGravity(Gravity.TOP);
- mKeyboardShortcutsDialog.show();
+ Recents.getSystemServices().requestKeyboardShortcuts(context,
+ new KeyboardShortcutsReceiver() {
+ @Override
+ public void onKeyboardShortcutsReceived(
+ final List<KeyboardShortcutGroup> result) {
+ KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
+ context.getString(R.string.keyboard_shortcut_group_system));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_home),
+ '\u2386', KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_back),
+ '\u007F', KeyEvent.META_META_ON));
+ systemGroup.addItem(new KeyboardShortcutInfo(
+ context.getString(R.string.keyboard_shortcut_group_system_recents),
+ '\u0009', KeyEvent.META_ALT_ON));
+ result.add(systemGroup);
+ Log.i(TAG, "Keyboard shortcuts received: " + String.valueOf(result));
+ showKeyboardShortcutsDialog(context);
+ }
+ });
} else {
dismissKeyboardShortcutsDialog();
}
}
+ private void showKeyboardShortcutsDialog(Context context) {
+ // Create dialog.
+ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(
+ LAYOUT_INFLATER_SERVICE);
+ final View keyboardShortcutsView = inflater.inflate(
+ R.layout.keyboard_shortcuts_view, null);
+
+ populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
+ R.id.keyboard_shortcuts_wrapper));
+ dialogBuilder.setView(keyboardShortcutsView);
+ mKeyboardShortcutsDialog = dialogBuilder.create();
+ mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
+
+ // Setup window.
+ Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
+ keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+ keyboardShortcutsWindow.setBackgroundDrawable(
+ new ColorDrawable(TRANSPARENT));
+ keyboardShortcutsWindow.setGravity(TOP);
+ keyboardShortcutsView.post(new Runnable() {
+ public void run() {
+ mKeyboardShortcutsDialog.show();
+ }
+ });
+ }
+
public void dismissKeyboardShortcutsDialog() {
if (mKeyboardShortcutsDialog != null) {
mKeyboardShortcutsDialog.dismiss();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 685df25910d6..7d142eca0bb4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -119,6 +119,7 @@ import android.widget.Toast;
import com.android.internal.R;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.os.IResultReceiver;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -10269,6 +10270,14 @@ public class WindowManagerService extends IWindowManager.Stub
listener);
}
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) {
+ try {
+ getFocusedWindow().mClient.requestAppKeyboardShortcuts(receiver);
+ } catch (RemoteException e) {
+ }
+ }
+
private final class LocalService extends WindowManagerInternal {
@Override
public void requestTraversalFromDisplayManager() {