1 /* 2 * Copyright (C) 2021 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.car.hvac; 18 19 import android.app.UiModeManager; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.content.res.Resources; 23 import android.graphics.Rect; 24 import android.view.KeyEvent; 25 import android.view.LayoutInflater; 26 import android.view.MotionEvent; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.WindowInsets; 30 31 import com.android.systemui.R; 32 import com.android.systemui.car.CarDeviceProvisionedController; 33 import com.android.systemui.car.window.OverlayPanelViewController; 34 import com.android.systemui.car.window.OverlayViewGlobalStateController; 35 import com.android.systemui.dagger.SysUISingleton; 36 import com.android.systemui.dagger.qualifiers.Main; 37 import com.android.systemui.statusbar.policy.ConfigurationController; 38 import com.android.wm.shell.animation.FlingAnimationUtils; 39 40 import javax.inject.Inject; 41 42 @SysUISingleton 43 public class HvacPanelOverlayViewController extends OverlayPanelViewController implements 44 ConfigurationController.ConfigurationListener { 45 46 private final Context mContext; 47 private final Resources mResources; 48 private final HvacController mHvacController; 49 private final UiModeManager mUiModeManager; 50 private final float mFullyOpenDimAmount; 51 52 private boolean mIsUiModeNight; 53 private float mCurrentDimAmount = 0f; 54 55 private HvacPanelView mHvacPanelView; 56 57 @Inject HvacPanelOverlayViewController(Context context, @Main Resources resources, HvacController hvacController, OverlayViewGlobalStateController overlayViewGlobalStateController, FlingAnimationUtils.Builder flingAnimationUtilsBuilder, CarDeviceProvisionedController carDeviceProvisionedController, ConfigurationController configurationController, UiModeManager uiModeManager)58 public HvacPanelOverlayViewController(Context context, 59 @Main Resources resources, 60 HvacController hvacController, 61 OverlayViewGlobalStateController overlayViewGlobalStateController, 62 FlingAnimationUtils.Builder flingAnimationUtilsBuilder, 63 CarDeviceProvisionedController carDeviceProvisionedController, 64 ConfigurationController configurationController, 65 UiModeManager uiModeManager) { 66 super(context, resources, R.id.hvac_panel_stub, overlayViewGlobalStateController, 67 flingAnimationUtilsBuilder, carDeviceProvisionedController); 68 mContext = context; 69 mResources = resources; 70 mHvacController = hvacController; 71 mUiModeManager = uiModeManager; 72 configurationController.addCallback(this); 73 mFullyOpenDimAmount = mContext.getResources().getFloat( 74 R.fraction.hvac_overlay_window_dim_amount); 75 } 76 77 @Override onFinishInflate()78 protected void onFinishInflate() { 79 super.onFinishInflate(); 80 81 View closeButton = getLayout().findViewById(R.id.hvac_panel_close_button); 82 if (closeButton != null) { 83 closeButton.setOnClickListener(v -> toggle()); 84 } 85 86 mHvacPanelView = getLayout().findViewById(R.id.hvac_panel); 87 mHvacController.registerHvacViews(mHvacPanelView); 88 89 mHvacPanelView.setKeyEventHandler((event) -> { 90 if (event.getKeyCode() != KeyEvent.KEYCODE_BACK) { 91 return false; 92 } 93 94 if (event.getAction() == KeyEvent.ACTION_UP && isPanelExpanded()) { 95 toggle(); 96 } 97 return true; 98 }); 99 } 100 101 @Override getInsetTypesToFit()102 protected int getInsetTypesToFit() { 103 return WindowInsets.Type.systemBars(); 104 } 105 106 @Override shouldShowStatusBarInsets()107 protected boolean shouldShowStatusBarInsets() { 108 return true; 109 } 110 111 @Override shouldShowNavigationBarInsets()112 protected boolean shouldShowNavigationBarInsets() { 113 return true; 114 } 115 116 @Override shouldAnimateCollapsePanel()117 protected boolean shouldAnimateCollapsePanel() { 118 return true; 119 } 120 121 @Override shouldAnimateExpandPanel()122 protected boolean shouldAnimateExpandPanel() { 123 return true; 124 } 125 126 @Override shouldAllowClosingScroll()127 protected boolean shouldAllowClosingScroll() { 128 return true; 129 } 130 131 @Override getDefaultDimAmount()132 protected float getDefaultDimAmount() { 133 return mCurrentDimAmount; 134 } 135 136 @Override getHandleBarViewId()137 protected Integer getHandleBarViewId() { 138 return R.id.handle_bar; 139 } 140 141 @Override getFocusAreaViewId()142 protected int getFocusAreaViewId() { 143 return R.id.hvac_panel_container; 144 } 145 146 @Override getSettleClosePercentage()147 protected int getSettleClosePercentage() { 148 return mResources.getInteger(R.integer.hvac_panel_settle_close_percentage); 149 } 150 151 @Override onAnimateCollapsePanel()152 protected void onAnimateCollapsePanel() { 153 // no-op. 154 } 155 156 @Override onAnimateExpandPanel()157 protected void onAnimateExpandPanel() { 158 // no-op. 159 } 160 161 @Override onCollapseAnimationEnd()162 protected void onCollapseAnimationEnd() { 163 // no-op. 164 } 165 166 @Override onExpandAnimationEnd()167 protected void onExpandAnimationEnd() { 168 // no-op. 169 } 170 171 @Override onOpenScrollStart()172 protected void onOpenScrollStart() { 173 // no-op. 174 } 175 176 @Override onTouchEvent(View view, MotionEvent event)177 protected void onTouchEvent(View view, MotionEvent event) { 178 if (mHvacPanelView == null) { 179 return; 180 } 181 Rect outBounds = new Rect(); 182 mHvacPanelView.getBoundsInWindow(outBounds, /* clipToParent= */ true); 183 if (isPanelExpanded() && (event.getAction() == MotionEvent.ACTION_UP) 184 && isTouchOutside(outBounds, event.getX(), event.getY())) { 185 toggle(); 186 } 187 } 188 189 @Override onScroll(int y)190 protected void onScroll(int y) { 191 super.onScroll(y); 192 193 float percentageOpen = 194 ((float) (mAnimateDirection > 0 ? y : getLayout().getHeight() - y)) 195 / getLayout().getHeight(); 196 mCurrentDimAmount = mFullyOpenDimAmount * percentageOpen; 197 getOverlayViewGlobalStateController().updateWindowDimBehind(this, mCurrentDimAmount); 198 } 199 isTouchOutside(Rect bounds, float x, float y)200 private boolean isTouchOutside(Rect bounds, float x, float y) { 201 return x < bounds.left || x > bounds.right || y < bounds.top || y > bounds.bottom; 202 } 203 204 @Override onConfigChanged(Configuration newConfig)205 public void onConfigChanged(Configuration newConfig) { 206 boolean isConfigNightMode = newConfig.isNightModeActive(); 207 208 // Only refresh UI on Night mode changes 209 if (isConfigNightMode != mIsUiModeNight) { 210 mIsUiModeNight = isConfigNightMode; 211 mUiModeManager.setNightModeActivated(mIsUiModeNight); 212 213 if (getLayout() == null) return; 214 mHvacPanelView = getLayout().findViewById(R.id.hvac_panel); 215 if (mHvacPanelView == null) return; 216 ViewGroup hvacViewGroupParent = (ViewGroup) mHvacPanelView.getParent(); 217 218 // cache properties of {@link HvacPanelView} 219 int inflatedId = mHvacPanelView.getId(); 220 ViewGroup.LayoutParams layoutParams = mHvacPanelView.getLayoutParams(); 221 HvacPanelView.KeyEventHandler hvacKeyEventHandler = mHvacPanelView 222 .getKeyEventHandler(); 223 int indexOfView = hvacViewGroupParent.indexOfChild(mHvacPanelView); 224 225 // remove {@link HvacPanelView} from its parent and reinflate it 226 hvacViewGroupParent.removeView(mHvacPanelView); 227 HvacPanelView newHvacPanelView = (HvacPanelView) LayoutInflater.from(mContext).inflate( 228 R.layout.hvac_panel, /* root= */ hvacViewGroupParent, 229 /* attachToRoot= */ false); 230 hvacViewGroupParent.addView(newHvacPanelView, indexOfView); 231 mHvacPanelView = newHvacPanelView; 232 233 // reset {@link HvacPanelView} cached properties 234 mHvacPanelView.setId(inflatedId); 235 mHvacPanelView.setLayoutParams(layoutParams); 236 mHvacController.registerHvacViews(mHvacPanelView); 237 mHvacPanelView.setKeyEventHandler(hvacKeyEventHandler); 238 } 239 } 240 } 241