1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.stackdivider; 18 19 import android.content.res.Configuration; 20 import android.os.RemoteException; 21 import android.view.IDockedStackListener; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 25 import com.android.systemui.R; 26 import com.android.systemui.SystemUI; 27 import com.android.systemui.recents.Recents; 28 import com.android.systemui.recents.misc.SystemServicesProxy; 29 30 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 31 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 32 33 import java.io.FileDescriptor; 34 import java.io.PrintWriter; 35 36 /** 37 * Controls the docked stack divider. 38 */ 39 public class Divider extends SystemUI { 40 private DividerWindowManager mWindowManager; 41 private DividerView mView; 42 private final DividerState mDividerState = new DividerState(); 43 private DockDividerVisibilityListener mDockDividerVisibilityListener; 44 private boolean mVisible = false; 45 private boolean mMinimized = false; 46 private boolean mAdjustedForIme = false; 47 private ForcedResizableInfoActivityController mForcedResizableController; 48 49 @Override 50 public void start() { 51 mWindowManager = new DividerWindowManager(mContext); 52 update(mContext.getResources().getConfiguration()); 53 putComponent(Divider.class, this); 54 mDockDividerVisibilityListener = new DockDividerVisibilityListener(); 55 SystemServicesProxy ssp = Recents.getSystemServices(); 56 ssp.registerDockedStackListener(mDockDividerVisibilityListener); 57 mForcedResizableController = new ForcedResizableInfoActivityController(mContext); 58 } 59 60 @Override 61 protected void onConfigurationChanged(Configuration newConfig) { 62 super.onConfigurationChanged(newConfig); 63 update(newConfig); 64 } 65 66 public DividerView getView() { 67 return mView; 68 } 69 70 private void addDivider(Configuration configuration) { 71 mView = (DividerView) 72 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null); 73 mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE); 74 final int size = mContext.getResources().getDimensionPixelSize( 75 com.android.internal.R.dimen.docked_stack_divider_thickness); 76 final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE; 77 final int width = landscape ? size : MATCH_PARENT; 78 final int height = landscape ? MATCH_PARENT : size; 79 mWindowManager.add(mView, width, height); 80 mView.injectDependencies(mWindowManager, mDividerState); 81 } 82 83 private void removeDivider() { 84 mWindowManager.remove(); 85 } 86 87 private void update(Configuration configuration) { 88 removeDivider(); 89 addDivider(configuration); 90 if (mMinimized) { 91 mView.setMinimizedDockStack(true); 92 updateTouchable(); 93 } 94 } 95 96 private void updateVisibility(final boolean visible) { 97 mView.post(new Runnable() { 98 @Override 99 public void run() { 100 if (mVisible != visible) { 101 mVisible = visible; 102 mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); 103 104 // Update state because animations won't finish. 105 mView.setMinimizedDockStack(mMinimized); 106 } 107 } 108 }); 109 } 110 111 private void updateMinimizedDockedStack(final boolean minimized, final long animDuration) { 112 mView.post(new Runnable() { 113 @Override 114 public void run() { 115 if (mMinimized != minimized) { 116 mMinimized = minimized; 117 updateTouchable(); 118 if (animDuration > 0) { 119 mView.setMinimizedDockStack(minimized, animDuration); 120 } else { 121 mView.setMinimizedDockStack(minimized); 122 } 123 } 124 } 125 }); 126 } 127 128 private void notifyDockedStackExistsChanged(final boolean exists) { 129 mView.post(new Runnable() { 130 @Override 131 public void run() { 132 mForcedResizableController.notifyDockedStackExistsChanged(exists); 133 } 134 }); 135 } 136 137 private void updateTouchable() { 138 mWindowManager.setTouchable(!mMinimized && !mAdjustedForIme); 139 } 140 141 @Override 142 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 143 pw.print(" mVisible="); pw.println(mVisible); 144 pw.print(" mMinimized="); pw.println(mMinimized); 145 pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme); 146 } 147 148 class DockDividerVisibilityListener extends IDockedStackListener.Stub { 149 150 @Override 151 public void onDividerVisibilityChanged(boolean visible) throws RemoteException { 152 updateVisibility(visible); 153 } 154 155 @Override 156 public void onDockedStackExistsChanged(boolean exists) throws RemoteException { 157 notifyDockedStackExistsChanged(exists); 158 } 159 160 @Override 161 public void onDockedStackMinimizedChanged(boolean minimized, long animDuration) 162 throws RemoteException { 163 updateMinimizedDockedStack(minimized, animDuration); 164 } 165 166 @Override 167 public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration) 168 throws RemoteException { 169 mView.post(() -> { 170 if (mAdjustedForIme != adjustedForIme) { 171 mAdjustedForIme = adjustedForIme; 172 updateTouchable(); 173 if (!mMinimized) { 174 if (animDuration > 0) { 175 mView.setAdjustedForIme(adjustedForIme, animDuration); 176 } else { 177 mView.setAdjustedForIme(adjustedForIme); 178 } 179 } 180 } 181 }); 182 } 183 184 @Override 185 public void onDockSideChanged(final int newDockSide) throws RemoteException { 186 mView.post(() -> mView.notifyDockSideChanged(newDockSide)); 187 } 188 } 189 } 190