blob: ec429a05e3ca7b99a19d9165c8eec0a312f6ae4c [file] [log] [blame]
/*
* 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.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static org.mockito.Mockito.mock;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerInternal;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
import android.os.PowerManagerInternal;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.input.InputManagerService;
import com.android.server.LocalServices;
import java.io.PrintWriter;
class TestWindowManagerPolicy implements WindowManagerPolicy {
private static final String TAG = "TestWindowManagerPolicy";
private static WindowManagerService sWm = null;
int rotationToReport = 0;
private Runnable mRunnableWhenAddingSplashScreen;
static synchronized WindowManagerService getWindowManagerService(Context context) {
if (sWm == null) {
// We only want to do this once for the test process as we don't want WM to try to
// register a bunch of local services again.
if (LocalServices.getService(DisplayManagerInternal.class) == null) {
LocalServices.addService(DisplayManagerInternal.class,
mock(DisplayManagerInternal.class));
}
if (LocalServices.getService(PowerManagerInternal.class) == null) {
LocalServices.addService(PowerManagerInternal.class,
mock(PowerManagerInternal.class));
}
sWm = WindowManagerService.main(context, mock(InputManagerService.class), true, false,
false, new TestWindowManagerPolicy());
}
return sWm;
}
@Override
public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
throws RemoteException {
}
@Override
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
}
@Override
public boolean isDefaultOrientationForced() {
return false;
}
@Override
public void setInitialDisplaySize(Display display, int width, int height, int density) {
}
@Override
public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
}
@Override
public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) {
return 0;
}
@Override
public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) {
return false;
}
@Override
public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
}
@Override
public void adjustConfigurationLw(Configuration config, int keyboardPresence,
int navigationPresence) {
}
@Override
public int windowTypeToLayerLw(int type) {
// TODO: figure-out a good way to keep this in-sync with PhoneWindowManager...sigh!
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return 2;
}
switch (type) {
case TYPE_PRESENTATION:
case TYPE_PRIVATE_PRESENTATION:
return 2;
case TYPE_WALLPAPER:
// wallpaper is at the bottom, though the window manager may move it.
return 2;
case TYPE_DOCK_DIVIDER:
return 2;
case TYPE_QS_DIALOG:
return 2;
case TYPE_PHONE:
return 3;
case TYPE_SEARCH_BAR:
case TYPE_VOICE_INTERACTION_STARTING:
return 4;
case TYPE_VOICE_INTERACTION:
// voice interaction layer is almost immediately above apps.
return 5;
case TYPE_INPUT_CONSUMER:
return 6;
case TYPE_SYSTEM_DIALOG:
return 7;
case TYPE_TOAST:
// toasts and the plugged-in battery thing
return 8;
case TYPE_PRIORITY_PHONE:
// SIM errors and unlock. Not sure if this really should be in a high layer.
return 9;
case TYPE_DREAM:
// used for Dreams (screensavers with TYPE_DREAM windows)
return 10;
case TYPE_SYSTEM_ALERT:
// like the ANR / app crashed dialogs
return 11;
case TYPE_INPUT_METHOD:
// on-screen keyboards and other such input method user interfaces go here.
return 12;
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
case TYPE_STATUS_BAR:
return 16;
case TYPE_STATUS_BAR_PANEL:
return 17;
case TYPE_KEYGUARD_DIALOG:
return 18;
case TYPE_VOLUME_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
return 19;
case TYPE_SYSTEM_OVERLAY:
// the on-screen volume indicator and controller shown when the user
// changes the device volume
return 20;
case TYPE_NAVIGATION_BAR:
// the navigation bar, if available, shows atop most things
return 21;
case TYPE_NAVIGATION_BAR_PANEL:
// some panels (e.g. search) need to show on top of the navigation bar
return 22;
case TYPE_SCREENSHOT:
// screenshot selection layer shouldn't go above system error, but it should cover
// navigation bars at the very least.
return 23;
case TYPE_SYSTEM_ERROR:
// system-level error dialogs
return 24;
case TYPE_MAGNIFICATION_OVERLAY:
// used to highlight the magnified portion of a display
return 25;
case TYPE_DISPLAY_OVERLAY:
// used to simulate secondary display devices
return 26;
case TYPE_DRAG:
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
return 27;
case TYPE_ACCESSIBILITY_OVERLAY:
// overlay put by accessibility services to intercept user interaction
return 28;
case TYPE_SECURE_SYSTEM_OVERLAY:
return 29;
case TYPE_BOOT_PROGRESS:
return 30;
case TYPE_POINTER:
// the (mouse) pointer layer
return 31;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
}
@Override
public int subWindowTypeToLayerLw(int type) {
// TODO: figure-out a good way to keep this in-sync with PhoneWindowManager...
switch (type) {
case TYPE_APPLICATION_PANEL:
case TYPE_APPLICATION_ATTACHED_DIALOG:
return 1;
case TYPE_APPLICATION_MEDIA:
return -2;
case TYPE_APPLICATION_MEDIA_OVERLAY:
return -1;
case TYPE_APPLICATION_SUB_PANEL:
return 2;
case TYPE_APPLICATION_ABOVE_SUB_PANEL:
return 3;
}
Log.e(TAG, "Unknown sub-window type: " + type);
return 0;
}
@Override
public int getMaxWallpaperLayer() {
return 0;
}
@Override
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
return 0;
}
@Override
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
return 0;
}
@Override
public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
return 0;
}
@Override
public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
return 0;
}
@Override
public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
return false;
}
@Override
public boolean canBeHiddenByKeyguardLw(WindowState win) {
return false;
}
/**
* Sets a runnable to run when adding a splash screen which gets executed after the window has
* been added but before returning the surface.
*/
void setRunnableWhenAddingSplashScreen(Runnable r) {
mRunnableWhenAddingSplashScreen = r;
}
@Override
public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme,
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
int logo, int windowFlags, Configuration overrideConfig, int displayId) {
final com.android.server.wm.WindowState window;
final AppWindowToken atoken;
synchronized (sWm.mWindowMap) {
atoken = WindowTestsBase.sDisplayContent.getAppWindowToken(appToken);
window = WindowTestsBase.createWindow(null, TYPE_APPLICATION_STARTING, atoken,
"Starting window");
atoken.startingWindow = window;
}
if (mRunnableWhenAddingSplashScreen != null) {
mRunnableWhenAddingSplashScreen.run();
mRunnableWhenAddingSplashScreen = null;
}
return () -> {
synchronized (sWm.mWindowMap) {
atoken.removeChild(window);
atoken.startingWindow = null;
}
};
}
@Override
public int prepareAddWindowLw(WindowState win,
WindowManager.LayoutParams attrs) {
return 0;
}
@Override
public void removeWindowLw(WindowState win) {
}
@Override
public int selectAnimationLw(WindowState win, int transit) {
return 0;
}
@Override
public void selectRotationAnimationLw(int[] anim) {
}
@Override
public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId,
boolean forceDefault) {
return false;
}
@Override
public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade) {
return null;
}
@Override
public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
return null;
}
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return 0;
}
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
return 0;
}
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event,
int policyFlags) {
return 0;
}
@Override
public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event,
int policyFlags) {
return null;
}
@Override
public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
int displayRotation, int uiMode) {
}
@Override
public int getSystemDecorLayerLw() {
return 0;
}
@Override
public void getContentRectLw(Rect r) {
}
@Override
public void layoutWindowLw(WindowState win,
WindowState attached) {
}
@Override
public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds,
int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets) {
return false;
}
@Override
public void finishLayoutLw() {
}
@Override
public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
}
@Override
public void applyPostLayoutPolicyLw(WindowState win,
WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget) {
}
@Override
public int finishPostLayoutPolicyLw() {
return 0;
}
@Override
public boolean allowAppAnimationsLw() {
return false;
}
@Override
public int focusChangedLw(WindowState lastFocus,
WindowState newFocus) {
return 0;
}
@Override
public void startedWakingUp() {
}
@Override
public void finishedWakingUp() {
}
@Override
public void startedGoingToSleep(int why) {
}
@Override
public void finishedGoingToSleep(int why) {
}
@Override
public void screenTurningOn(ScreenOnListener screenOnListener) {
}
@Override
public void screenTurnedOn() {
}
@Override
public void screenTurnedOff() {
}
@Override
public boolean isScreenOn() {
return true;
}
@Override
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
}
@Override
public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) {
}
@Override
public void enableKeyguard(boolean enabled) {
}
@Override
public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
}
@Override
public boolean isKeyguardLocked() {
return false;
}
@Override
public boolean isKeyguardSecure(int userId) {
return false;
}
@Override
public boolean isKeyguardOccluded() {
return false;
}
@Override
public boolean isKeyguardTrustedLw() {
return false;
}
@Override
public boolean isKeyguardShowingAndNotOccluded() {
return false;
}
@Override
public boolean inKeyguardRestrictedKeyInputMode() {
return false;
}
@Override
public void dismissKeyguardLw(@Nullable IKeyguardDismissCallback callback) {
}
@Override
public boolean isKeyguardDrawnLw() {
return false;
}
@Override
public boolean isShowingDreamLw() {
return false;
}
@Override
public void onKeyguardOccludedChangedLw(boolean occluded) {
}
@Override
public int rotationForOrientationLw(int orientation,
int lastRotation) {
return rotationToReport;
}
@Override
public boolean rotationHasCompatibleMetricsLw(int orientation,
int rotation) {
return false;
}
@Override
public void setRotationLw(int rotation) {
}
@Override
public void setSafeMode(boolean safeMode) {
}
@Override
public void systemReady() {
}
@Override
public void systemBooted() {
}
@Override
public void showBootMessage(CharSequence msg, boolean always) {
}
@Override
public void hideBootMessages() {
}
@Override
public void userActivity() {
}
@Override
public void enableScreenAfterBoot() {
}
@Override
public void setCurrentOrientationLw(int newOrientation) {
}
@Override
public boolean performHapticFeedbackLw(WindowState win, int effectId,
boolean always) {
return false;
}
@Override
public void keepScreenOnStartedLw() {
}
@Override
public void keepScreenOnStoppedLw() {
}
@Override
public int getUserRotationMode() {
return 0;
}
@Override
public void setUserRotationMode(int mode,
int rotation) {
}
@Override
public int adjustSystemUiVisibilityLw(int visibility) {
return 0;
}
@Override
public boolean hasNavigationBar() {
return false;
}
@Override
public void lockNow(Bundle options) {
}
@Override
public void setLastInputMethodWindowLw(WindowState ime,
WindowState target) {
}
@Override
public void showRecentApps(boolean fromHome) {
}
@Override
public void showGlobalActions() {
}
@Override
public int getInputMethodWindowVisibleHeightLw() {
return 0;
}
@Override
public void setCurrentUserLw(int newUserId) {
}
@Override
public void setSwitchingUser(boolean switching) {
}
@Override
public void dump(String prefix, PrintWriter writer, String[] args) {
}
@Override
public boolean canMagnifyWindow(int windowType) {
return false;
}
@Override
public boolean isTopLevelWindow(int windowType) {
return false;
}
@Override
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
}
@Override
public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight,
Rect outInsets) {
}
@Override
public boolean isNavBarForcedShownLw(WindowState win) {
return false;
}
@Override
public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,
Rect outInsets) {
}
@Override
public boolean isDockSideAllowed(int dockSide) {
return false;
}
@Override
public void onConfigurationChanged() {
}
@Override
public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) {
return false;
}
@Override
public void setTvPipVisibilityLw(boolean visible) {
}
@Override
public void setRecentsVisibilityLw(boolean visible) {
}
}