diff options
11 files changed, 249 insertions, 3 deletions
diff --git a/Android.mk b/Android.mk index 683cdf80bc5d..2ee7600d3288 100644 --- a/Android.mk +++ b/Android.mk @@ -311,6 +311,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/policy/IKeyguardExitCallback.aidl \ core/java/com/android/internal/policy/IKeyguardService.aidl \ core/java/com/android/internal/policy/IKeyguardStateCallback.aidl \ + core/java/com/android/internal/policy/IShortcutService.aidl \ core/java/com/android/internal/os/IDropBoxManagerService.aidl \ core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl \ core/java/com/android/internal/os/IResultReceiver.aidl \ diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 5b9930bb34a7..9543acfba51b 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -20,6 +20,7 @@ import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.os.IResultReceiver; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; +import com.android.internal.policy.IShortcutService; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; @@ -387,4 +388,11 @@ interface IWindowManager * Retrieves the current stable insets from the primary display. */ void getStableInsets(out Rect outInsets); + + /** + * Register shortcut key. Shortcut code is packed as: + * (MetaState << Integer.SIZE) | KeyCode + * @hide + */ + void registerShortcutKey(in long shortcutCode, IShortcutService keySubscriber); } diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index 2fbfd2d13b40..b011414bc556 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -29,7 +29,9 @@ import android.graphics.RectF; import android.os.Bundle; import android.os.IBinder; import android.os.Looper; +import android.os.RemoteException; import android.view.animation.Animation; +import com.android.internal.policy.IShortcutService; import java.io.PrintWriter; import java.lang.annotation.Retention; @@ -121,6 +123,14 @@ public interface WindowManagerPolicy { public final static int ACTION_PASS_TO_USER = 0x00000001; /** + * Register shortcuts for window manager to dispatch. + * Shortcut code is packed as (metaState << Integer.SIZE) | keyCode + * @hide + */ + void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) + throws RemoteException; + + /** * Interface to the Window Manager state associated with a particular * window. You can hold on to an instance of this interface from the call * to prepareAddWindow() until removeWindow(). diff --git a/core/java/com/android/internal/policy/IShortcutService.aidl b/core/java/com/android/internal/policy/IShortcutService.aidl new file mode 100644 index 000000000000..85507282b4de --- /dev/null +++ b/core/java/com/android/internal/policy/IShortcutService.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 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; + +/** + * An interface to notify the shortcut service that a shortcut key is pressed + * @hide + */ +oneway interface IShortcutService { + /** + * @param shortcutCode the keycode packed with meta information + */ + void notifyShortcutKeyPressed(long shortcutCode); +} + diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 472648a2f7f6..b2b612787fd2 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -54,7 +54,8 @@ public class SystemUIApplication extends Application { com.android.systemui.power.PowerUI.class, com.android.systemui.media.RingtonePlayer.class, com.android.systemui.keyboard.KeyboardUI.class, - com.android.systemui.tv.pip.PipUI.class + com.android.systemui.tv.pip.PipUI.class, + com.android.systemui.shortcut.ShortcutKeyDispatcher.class }; /** @@ -143,12 +144,14 @@ public class SystemUIApplication extends Application { Class<?> cl = services[i]; if (DEBUG) Log.d(TAG, "loading: " + cl); try { - mServices[i] = (SystemUI) cl.newInstance(); + Object newService = SystemUIFactory.getInstance().createInstance(cl); + mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } + mServices[i].mContext = this; mServices[i].mComponents = mComponents; if (DEBUG) Log.d(TAG, "running: " + mServices[i]); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 41cce74a31dc..913b2b346b34 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -23,6 +23,7 @@ import android.view.ViewGroup; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.ViewMediatorCallback; +import com.android.systemui.shortcut.ShortcutKeyDispatcher; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.phone.KeyguardBouncer; import com.android.systemui.statusbar.phone.ScrimController; @@ -74,4 +75,8 @@ public class SystemUIFactory { View headsUpScrim, boolean scrimSrcEnabled) { return new ScrimController(scrimBehind, scrimInFront, headsUpScrim, scrimSrcEnabled); } + + public <T> T createInstance(Class<T> classType) { + return null; + } } diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java new file mode 100644 index 000000000000..8f8683b4ea23 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 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.systemui.shortcut; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ServiceInfo; +import android.os.RemoteException; +import android.util.Log; +import android.view.IWindowManager; +import android.view.KeyEvent; +import android.view.WindowManagerGlobal; +import android.view.accessibility.AccessibilityManager; +import com.android.settingslib.accessibility.AccessibilityUtils; +import com.android.systemui.R; +import com.android.systemui.SystemUI; + +import java.util.List; +import java.util.Set; + +/** + * Dispatches shortcut to System UI components + */ +public class ShortcutKeyDispatcher extends SystemUI + implements ShortcutKeyServiceProxy.Callbacks { + + private static final String TAG = "ShortcutKeyDispatcher"; + + private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this); + private IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService(); + + protected final long META_MASK = ((long) KeyEvent.META_META_ON) << Integer.SIZE; + protected final long ALT_MASK = ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; + protected final long CTRL_MASK = ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; + protected final long SHIFT_MASK = ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; + + /** + * Registers a shortcut key to window manager. + * @param shortcutCode packed representation of shortcut key code and meta information + */ + public void registerShortcutKey(long shortcutCode) { + try { + windowManagerService.registerShortcutKey(shortcutCode, mShortcutKeyServiceProxy); + } catch (RemoteException e) { + // Do nothing + } + } + + @Override + public void onShortcutKeyPressed(long shortcutCode) {} + + @Override + public void start() {} +} diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java new file mode 100644 index 000000000000..8ec862e1fdec --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2016 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.systemui.shortcut; + +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; +import com.android.internal.policy.IShortcutService; + +/** + * This class takes functions from IShortcutService that come in binder pool threads and + * post them onto shortcut handlers. + */ +public class ShortcutKeyServiceProxy extends IShortcutService.Stub { + private static final int MSG_SHORTCUT_RECEIVED = 1; + + private final Object mLock = new Object(); + private Callbacks mCallbacks; + private final Handler mHandler = new H(); + + public interface Callbacks { + void onShortcutKeyPressed(long shortcutCode); + } + + public ShortcutKeyServiceProxy(Callbacks callbacks) { mCallbacks = callbacks; } + + @Override + public void notifyShortcutKeyPressed(long shortcutCode) throws RemoteException { + synchronized (mLock) { + mHandler.obtainMessage(MSG_SHORTCUT_RECEIVED, shortcutCode).sendToTarget(); + } + } + + private final class H extends Handler { + public void handleMessage(Message msg) { + final int what = msg.what; + switch (what) { + case MSG_SHORTCUT_RECEIVED: + mCallbacks.onShortcutKeyPressed((Long)msg.obj); + break; + } + } + } +} diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index e1a029964279..6320413a452a 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -107,6 +107,7 @@ import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.util.LongSparseArray; import android.view.Display; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -135,6 +136,7 @@ import android.view.animation.AnimationUtils; import com.android.internal.R; import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.PhoneWindow; +import com.android.internal.policy.IShortcutService; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenShapeHelper; import com.android.internal.widget.PointerLocationView; @@ -336,6 +338,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { int[] mNavigationBarHeightForRotationInCarMode = new int[4]; int[] mNavigationBarWidthForRotationInCarMode = new int[4]; + private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>(); + // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. // This is for car dock and this is updated from resource. private boolean mEnableCarDockHomeCapture = true; @@ -3100,7 +3104,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { dispatchDirectAudioEvent(event); return -1; } - } else if (KeyEvent.isMetaKey(keyCode)) { + } + + if (KeyEvent.isMetaKey(keyCode)) { if (down) { mPendingMetaAction = true; } else if (mPendingMetaAction) { @@ -3215,6 +3221,35 @@ public class PhoneWindowManager implements WindowManagerPolicy { return -1; } + if (down) { + long shortcutCode = (long) keyCode; + if (event.isCtrlPressed()) { + shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; + } + + if (event.isAltPressed()) { + shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; + } + + if (event.isShiftPressed()) { + shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; + } + + if (event.isMetaPressed()) { + shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; + } + + IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); + if (shortcutService != null) { + try { + shortcutService.notifyShortcutKeyPressed(shortcutCode); + } catch (RemoteException e) { + mShortcutKeyServices.delete(shortcutCode); + } + return -1; + } + } + // Reserve all the META modifier combos for system behavior if ((metaState & KeyEvent.META_META_ON) != 0) { return -1; @@ -3304,6 +3339,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { return false; } + public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) + throws RemoteException { + synchronized (mLock) { + IShortcutService service = mShortcutKeyServices.get(shortcutCode); + if (service != null && service.asBinder().isBinderAlive()) { + throw new RemoteException("Key already exists."); + } + + mShortcutKeyServices.put(shortcutCode, shortcutService); + } + } + private void launchAssistLongPressAction() { performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c7373081d7de..69d2d20a9018 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -120,6 +120,7 @@ import android.widget.Toast; import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.os.IResultReceiver; +import com.android.internal.policy.IShortcutService; import com.android.internal.util.FastPrintWriter; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -10604,6 +10605,16 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver) + throws RemoteException { + if (!checkCallingPermission(Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS, + "registerShortcutKey")) { + throw new SecurityException( + "Requires REGISTER_WINDOW_MANAGER_LISTENERS permission"); + } + mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver); + } + private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index 8d1b124809a3..d2103c811d3e 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -20,6 +20,7 @@ import android.graphics.Point; import android.graphics.Rect; import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.os.IResultReceiver; +import com.android.internal.policy.IShortcutService; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; @@ -566,4 +567,8 @@ public class IWindowManagerImpl implements IWindowManager { @Override public void getStableInsets(Rect outInsets) throws RemoteException { } + + @Override + public void registerShortcutKey(long shortcutCode, IShortcutService service) + throws RemoteException {} } |