blob: cd2074fd64b8ea9979dae777535cf04dd103dd4c [file] [log] [blame]
/*
* 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 com.android.systemui.stackdivider;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import android.content.res.Configuration;
import android.os.RemoteException;
import android.util.Log;
import android.view.IDockedStackListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManagerGlobal;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.recents.Recents;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Controls the docked stack divider.
*/
public class Divider extends SystemUI implements DividerView.DividerCallbacks {
private static final String TAG = "Divider";
private DividerWindowManager mWindowManager;
private DividerView mView;
private final DividerState mDividerState = new DividerState();
private DockDividerVisibilityListener mDockDividerVisibilityListener;
private boolean mVisible = false;
private boolean mMinimized = false;
private boolean mAdjustedForIme = false;
private boolean mHomeStackResizable = false;
private ForcedResizableInfoActivityController mForcedResizableController;
@Override
public void start() {
mWindowManager = new DividerWindowManager(mContext);
update(mContext.getResources().getConfiguration());
putComponent(Divider.class, this);
mDockDividerVisibilityListener = new DockDividerVisibilityListener();
try {
WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
mDockDividerVisibilityListener);
} catch (Exception e) {
Log.e(TAG, "Failed to register docked stack listener", e);
}
mForcedResizableController = new ForcedResizableInfoActivityController(mContext);
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
update(newConfig);
}
public DividerView getView() {
return mView;
}
public boolean isMinimized() {
return mMinimized;
}
public boolean isHomeStackResizable() {
return mHomeStackResizable;
}
private void addDivider(Configuration configuration) {
mView = (DividerView)
LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
mView.injectDependencies(mWindowManager, mDividerState, this);
mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
final int size = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
final int width = landscape ? size : MATCH_PARENT;
final int height = landscape ? MATCH_PARENT : size;
mWindowManager.add(mView, width, height);
}
private void removeDivider() {
if (mView != null) {
mView.onDividerRemoved();
}
mWindowManager.remove();
}
private void update(Configuration configuration) {
removeDivider();
addDivider(configuration);
if (mMinimized) {
mView.setMinimizedDockStack(true, mHomeStackResizable);
updateTouchable();
}
}
private void updateVisibility(final boolean visible) {
mView.post(new Runnable() {
@Override
public void run() {
if (mVisible != visible) {
mVisible = visible;
mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
// Update state because animations won't finish.
mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
}
}
});
}
private void updateMinimizedDockedStack(final boolean minimized, final long animDuration,
final boolean isHomeStackResizable) {
mView.post(new Runnable() {
@Override
public void run() {
mHomeStackResizable = isHomeStackResizable;
if (mMinimized != minimized) {
mMinimized = minimized;
updateTouchable();
if (animDuration > 0) {
mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable);
} else {
mView.setMinimizedDockStack(minimized, isHomeStackResizable);
}
}
}
});
}
private void notifyDockedStackExistsChanged(final boolean exists) {
mView.post(new Runnable() {
@Override
public void run() {
mForcedResizableController.notifyDockedStackExistsChanged(exists);
}
});
}
private void updateTouchable() {
mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
}
public void onRecentsActivityStarting() {
if (mView != null) {
mView.onRecentsActivityStarting();
}
}
/**
* Workaround for b/62528361, at the time recents has drawn, it may happen before a
* configuration change to the Divider, and internally, the event will be posted to the
* subscriber, or DividerView, which has been removed and prevented from resizing. Instead,
* register the event handler here and proxy the event to the current DividerView.
*/
public void onRecentsDrawn() {
if (mView != null) {
mView.onRecentsDrawn();
}
}
public void onUndockingTask() {
if (mView != null) {
mView.onUndockingTask();
}
}
public void onDockedFirstAnimationFrame() {
if (mView != null) {
mView.onDockedFirstAnimationFrame();
}
}
public void onDockedTopTask() {
if (mView != null) {
mView.onDockedTopTask();
}
}
public void onAppTransitionFinished() {
mForcedResizableController.onAppTransitionFinished();
}
@Override
public void onDraggingStart() {
mForcedResizableController.onDraggingStart();
}
@Override
public void onDraggingEnd() {
mForcedResizableController.onDraggingEnd();
}
@Override
public void growRecents() {
Recents recents = getComponent(Recents.class);
if (recents != null) {
recents.growRecents();
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.print(" mVisible="); pw.println(mVisible);
pw.print(" mMinimized="); pw.println(mMinimized);
pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
}
class DockDividerVisibilityListener extends IDockedStackListener.Stub {
@Override
public void onDividerVisibilityChanged(boolean visible) throws RemoteException {
updateVisibility(visible);
}
@Override
public void onDockedStackExistsChanged(boolean exists) throws RemoteException {
notifyDockedStackExistsChanged(exists);
}
@Override
public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
boolean isHomeStackResizable) throws RemoteException {
mHomeStackResizable = isHomeStackResizable;
updateMinimizedDockedStack(minimized, animDuration, isHomeStackResizable);
}
@Override
public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration)
throws RemoteException {
mView.post(() -> {
if (mAdjustedForIme != adjustedForIme) {
mAdjustedForIme = adjustedForIme;
updateTouchable();
if (!mMinimized) {
if (animDuration > 0) {
mView.setAdjustedForIme(adjustedForIme, animDuration);
} else {
mView.setAdjustedForIme(adjustedForIme);
}
}
}
});
}
@Override
public void onDockSideChanged(final int newDockSide) throws RemoteException {
mView.post(() -> mView.notifyDockSideChanged(newDockSide));
}
}
}