blob: 9c456eecc1acd29ff35aa15b498f0fd27b2cb9b0 [file] [log] [blame]
/*
* Copyright (C) 2020 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.window;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Binder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.ConfigurationController;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
* Controls the expansion state of the primary window which will contain all of the fullscreen sysui
* behavior. This window still has a collapsed state in order to watch for swipe events to expand
* this window for the notification panel.
*/
@Singleton
public class SystemUIOverlayWindowController implements
ConfigurationController.ConfigurationListener {
private final Context mContext;
private final Resources mResources;
private final WindowManager mWindowManager;
private final int mStatusBarHeight;
private final int mNavBarHeight;
private final int mDisplayHeight;
private ViewGroup mBaseLayout;
private WindowManager.LayoutParams mLp;
private WindowManager.LayoutParams mLpChanged;
private boolean mIsAttached = false;
@Inject
public SystemUIOverlayWindowController(
Context context,
@Main Resources resources,
WindowManager windowManager,
ConfigurationController configurationController
) {
mContext = context;
mResources = resources;
mWindowManager = windowManager;
Point display = new Point();
mWindowManager.getDefaultDisplay().getSize(display);
mDisplayHeight = display.y;
mStatusBarHeight = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
mNavBarHeight = mResources.getDimensionPixelSize(R.dimen.navigation_bar_height);
mLpChanged = new WindowManager.LayoutParams();
mBaseLayout = (ViewGroup) LayoutInflater.from(context)
.inflate(R.layout.sysui_overlay_window, /* root= */ null, false);
configurationController.addCallback(this);
}
/** Returns the base view of the primary window. */
public ViewGroup getBaseLayout() {
return mBaseLayout;
}
/** Returns {@code true} if the window is already attached. */
public boolean isAttached() {
return mIsAttached;
}
/** Attaches the window to the window manager. */
public void attach() {
if (mIsAttached) {
return;
}
mIsAttached = true;
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
mLp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
mStatusBarHeight,
WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.TRANSLUCENT);
mLp.token = new Binder();
mLp.gravity = Gravity.TOP;
mLp.setFitInsetsTypes(/* types= */ 0);
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLp.setTitle("SystemUIOverlayWindow");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mWindowManager.addView(mBaseLayout, mLp);
mLpChanged.copyFrom(mLp);
}
/** Sets the window to the expanded state. */
public void setWindowExpanded(boolean expanded) {
if (expanded) {
// TODO: Update this so that the windowing type gets the full height of the display
// when we use MATCH_PARENT.
mLpChanged.height = mDisplayHeight + mNavBarHeight;
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
} else {
mLpChanged.height = mStatusBarHeight;
// TODO: Allow touches to go through to the status bar to handle notification panel.
mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
}
updateWindow();
}
/** Returns {@code true} if the window is expanded */
public boolean isWindowExpanded() {
return mLp.height != mStatusBarHeight;
}
private void updateWindow() {
if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
if (isAttached()) {
mWindowManager.updateViewLayout(mBaseLayout, mLp);
}
}
}
}