1 /*
2  * Copyright (C) 2014 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.statusbar.policy;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.res.Resources;
22 import android.util.ArraySet;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.view.ViewGroup;
26 import android.widget.FrameLayout;
27 
28 import com.android.systemui.R;
29 import com.android.systemui.settings.brightness.BrightnessSliderController;
30 import com.android.systemui.settings.brightness.ToggleSlider;
31 import com.android.systemui.shade.NotificationShadeWindowView;
32 import com.android.systemui.shade.ShadeViewController;
33 import com.android.systemui.statusbar.NotificationShadeDepthController;
34 
35 import java.util.Objects;
36 import java.util.function.Consumer;
37 
38 /**
39  * Controls showing and hiding of the brightness mirror.
40  */
41 public class BrightnessMirrorController
42         implements CallbackController<BrightnessMirrorController.BrightnessMirrorListener> {
43 
44     private final NotificationShadeWindowView mStatusBarWindow;
45     private final Consumer<Boolean> mVisibilityCallback;
46     private final ShadeViewController mNotificationPanel;
47     private final NotificationShadeDepthController mDepthController;
48     private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
49     private final BrightnessSliderController.Factory mToggleSliderFactory;
50     private BrightnessSliderController mToggleSliderController;
51     private final int[] mInt2Cache = new int[2];
52     private FrameLayout mBrightnessMirror;
53     private int mBrightnessMirrorBackgroundPadding;
54     private int mLastBrightnessSliderWidth = -1;
55 
BrightnessMirrorController(NotificationShadeWindowView statusBarWindow, ShadeViewController shadeViewController, NotificationShadeDepthController notificationShadeDepthController, BrightnessSliderController.Factory factory, @NonNull Consumer<Boolean> visibilityCallback)56     public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
57             ShadeViewController shadeViewController,
58             NotificationShadeDepthController notificationShadeDepthController,
59             BrightnessSliderController.Factory factory,
60             @NonNull Consumer<Boolean> visibilityCallback) {
61         mStatusBarWindow = statusBarWindow;
62         mToggleSliderFactory = factory;
63         mBrightnessMirror = statusBarWindow.findViewById(R.id.brightness_mirror_container);
64         mToggleSliderController = setMirrorLayout();
65         mNotificationPanel = shadeViewController;
66         mDepthController = notificationShadeDepthController;
67         mNotificationPanel.setAlphaChangeAnimationEndAction(() -> {
68             mBrightnessMirror.setVisibility(View.INVISIBLE);
69         });
70         mVisibilityCallback = visibilityCallback;
71         updateResources();
72     }
73 
showMirror()74     public void showMirror() {
75         mBrightnessMirror.setVisibility(View.VISIBLE);
76         mVisibilityCallback.accept(true);
77         mNotificationPanel.setAlpha(0, true /* animate */);
78         mDepthController.setBrightnessMirrorVisible(true);
79     }
80 
hideMirror()81     public void hideMirror() {
82         mVisibilityCallback.accept(false);
83         mNotificationPanel.setAlpha(255, true /* animate */);
84         mDepthController.setBrightnessMirrorVisible(false);
85     }
86 
87     /**
88      * Set the location and size of the mirror container to match that of the slider in QS
89      * @param original the original view in QS
90      */
setLocationAndSize(View original)91     public void setLocationAndSize(View original) {
92         original.getLocationInWindow(mInt2Cache);
93 
94         // Original is slightly larger than the mirror, so make sure to use the center for the
95         // positioning.
96         int originalX = mInt2Cache[0] - mBrightnessMirrorBackgroundPadding;
97         int originalY = mInt2Cache[1] - mBrightnessMirrorBackgroundPadding;
98         mBrightnessMirror.setTranslationX(0);
99         mBrightnessMirror.setTranslationY(0);
100         mBrightnessMirror.getLocationInWindow(mInt2Cache);
101         int mirrorX = mInt2Cache[0];
102         int mirrorY = mInt2Cache[1];
103         mBrightnessMirror.setTranslationX(originalX - mirrorX);
104         mBrightnessMirror.setTranslationY(originalY - mirrorY);
105 
106         // Set the brightness mirror container to be the width of the mirror + 2 times the padding
107         int newWidth = original.getMeasuredWidth() + 2 * mBrightnessMirrorBackgroundPadding;
108         if (newWidth != mLastBrightnessSliderWidth) {
109             ViewGroup.LayoutParams lp = mBrightnessMirror.getLayoutParams();
110             lp.width = newWidth;
111             mBrightnessMirror.setLayoutParams(lp);
112         }
113     }
114 
getToggleSlider()115     public ToggleSlider getToggleSlider() {
116         return mToggleSliderController;
117     }
118 
updateResources()119     public void updateResources() {
120         Resources r = mBrightnessMirror.getResources();
121         mBrightnessMirrorBackgroundPadding = r
122                 .getDimensionPixelSize(R.dimen.rounded_slider_background_padding);
123         mBrightnessMirror.setPadding(
124                 mBrightnessMirrorBackgroundPadding,
125                 mBrightnessMirrorBackgroundPadding,
126                 mBrightnessMirrorBackgroundPadding,
127                 mBrightnessMirrorBackgroundPadding
128         );
129     }
130 
onOverlayChanged()131     public void onOverlayChanged() {
132         reinflate();
133     }
134 
onDensityOrFontScaleChanged()135     public void onDensityOrFontScaleChanged() {
136         reinflate();
137     }
138 
setMirrorLayout()139     private BrightnessSliderController setMirrorLayout() {
140         Context context = mBrightnessMirror.getContext();
141         BrightnessSliderController controller = mToggleSliderFactory.create(context,
142                 mBrightnessMirror);
143         controller.init();
144 
145         mBrightnessMirror.addView(controller.getRootView(), ViewGroup.LayoutParams.MATCH_PARENT,
146                 ViewGroup.LayoutParams.WRAP_CONTENT);
147 
148         return controller;
149     }
150 
reinflate()151     private void reinflate() {
152         int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
153         mStatusBarWindow.removeView(mBrightnessMirror);
154         mBrightnessMirror = (FrameLayout) LayoutInflater.from(mStatusBarWindow.getContext())
155                 .inflate(R.layout.brightness_mirror_container, mStatusBarWindow, false);
156         mToggleSliderController = setMirrorLayout();
157         mStatusBarWindow.addView(mBrightnessMirror, index);
158         updateResources();
159 
160         for (int i = 0; i < mBrightnessMirrorListeners.size(); i++) {
161             mBrightnessMirrorListeners.valueAt(i).onBrightnessMirrorReinflated(mBrightnessMirror);
162         }
163     }
164 
165     @Override
addCallback(@onNull BrightnessMirrorListener listener)166     public void addCallback(@NonNull BrightnessMirrorListener listener) {
167         Objects.requireNonNull(listener);
168         mBrightnessMirrorListeners.add(listener);
169     }
170 
171     @Override
removeCallback(@onNull BrightnessMirrorListener listener)172     public void removeCallback(@NonNull BrightnessMirrorListener listener) {
173         mBrightnessMirrorListeners.remove(listener);
174     }
175 
onUiModeChanged()176     public void onUiModeChanged() {
177         reinflate();
178     }
179 
180     public interface BrightnessMirrorListener {
onBrightnessMirrorReinflated(View brightnessMirror)181         void onBrightnessMirrorReinflated(View brightnessMirror);
182     }
183 }
184