• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.navigationbar;
18 
19 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
20 
21 import static com.android.systemui.util.Utils.isGesturalModeOnDefaultDisplay;
22 
23 import android.graphics.Rect;
24 import android.os.Handler;
25 import android.os.RemoteException;
26 import android.util.SparseArray;
27 import android.view.Display;
28 import android.view.IWallpaperVisibilityListener;
29 import android.view.IWindowManager;
30 import android.view.View;
31 
32 import com.android.systemui.Dependency;
33 import com.android.systemui.R;
34 import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
35 import com.android.systemui.statusbar.CommandQueue;
36 import com.android.systemui.statusbar.phone.BarTransitions;
37 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
38 
39 import java.io.PrintWriter;
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 public final class NavigationBarTransitions extends BarTransitions implements
44         LightBarTransitionsController.DarkIntensityApplier {
45 
46     public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
47     public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
48 
49     /**
50      * Notified when the color of nav bar elements changes.
51      */
52     public interface DarkIntensityListener {
53         /**
54          * Called when the color of nav bar elements changes.
55          * @param darkIntensity 0 is the lightest color, 1 is the darkest.
56          */
onDarkIntensity(float darkIntensity)57         void onDarkIntensity(float darkIntensity);
58     }
59 
60     private final NavigationBarView mView;
61     private final LightBarTransitionsController mLightTransitionsController;
62     private final boolean mAllowAutoDimWallpaperNotVisible;
63     private boolean mWallpaperVisible;
64 
65     private boolean mLightsOut;
66     private boolean mAutoDim;
67     private View mNavButtons;
68     private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
69     private List<DarkIntensityListener> mDarkIntensityListeners;
70 
71     private final Handler mHandler = Handler.getMain();
72     private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
73             new IWallpaperVisibilityListener.Stub() {
74         @Override
75         public void onWallpaperVisibilityChanged(boolean newVisibility,
76         int displayId) throws RemoteException {
77             mWallpaperVisible = newVisibility;
78             mHandler.post(() -> applyLightsOut(true, false));
79         }
80     };
81 
NavigationBarTransitions(NavigationBarView view, CommandQueue commandQueue)82     public NavigationBarTransitions(NavigationBarView view, CommandQueue commandQueue) {
83         super(view, R.drawable.nav_background);
84         mView = view;
85         mLightTransitionsController = new LightBarTransitionsController(
86                 view.getContext(), this, commandQueue);
87         mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
88                 .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
89         mDarkIntensityListeners = new ArrayList();
90 
91         IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
92         try {
93             mWallpaperVisible = windowManagerService.registerWallpaperVisibilityListener(
94                     mWallpaperVisibilityListener, Display.DEFAULT_DISPLAY);
95         } catch (RemoteException e) {
96         }
97         mView.addOnLayoutChangeListener(
98                 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
99                     View currentView = mView.getCurrentView();
100                     if (currentView != null) {
101                         mNavButtons = currentView.findViewById(R.id.nav_buttons);
102                         applyLightsOut(false, true);
103                     }
104                 });
105         View currentView = mView.getCurrentView();
106         if (currentView != null) {
107             mNavButtons = currentView.findViewById(R.id.nav_buttons);
108         }
109     }
110 
init()111     public void init() {
112         applyModeBackground(-1, getMode(), false /*animate*/);
113         applyLightsOut(false /*animate*/, true /*force*/);
114     }
115 
116     @Override
destroy()117     public void destroy() {
118         IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
119         try {
120             windowManagerService.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
121                     Display.DEFAULT_DISPLAY);
122         } catch (RemoteException e) {
123         }
124     }
125 
126     @Override
setAutoDim(boolean autoDim)127     public void setAutoDim(boolean autoDim) {
128         // Ensure we aren't in gestural nav if we are triggering auto dim
129         if (autoDim && isGesturalModeOnDefaultDisplay(mView.getContext(), mNavBarMode)) return;
130         if (mAutoDim == autoDim) return;
131         mAutoDim = autoDim;
132         applyLightsOut(true, false);
133     }
134 
setBackgroundFrame(Rect frame)135     void setBackgroundFrame(Rect frame) {
136         mBarBackground.setFrame(frame);
137     }
138 
setBackgroundOverrideAlpha(float alpha)139     void setBackgroundOverrideAlpha(float alpha) {
140         mBarBackground.setOverrideAlpha(alpha);
141     }
142 
143     @Override
isLightsOut(int mode)144     protected boolean isLightsOut(int mode) {
145         return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim
146                 && !mWallpaperVisible && mode != MODE_WARNING);
147     }
148 
getLightTransitionsController()149     public LightBarTransitionsController getLightTransitionsController() {
150         return mLightTransitionsController;
151     }
152 
153     @Override
onTransition(int oldMode, int newMode, boolean animate)154     protected void onTransition(int oldMode, int newMode, boolean animate) {
155         super.onTransition(oldMode, newMode, animate);
156         applyLightsOut(animate, false /*force*/);
157         mView.onBarTransition(newMode);
158     }
159 
applyLightsOut(boolean animate, boolean force)160     private void applyLightsOut(boolean animate, boolean force) {
161         // apply to lights out
162         applyLightsOut(isLightsOut(getMode()), animate, force);
163     }
164 
applyLightsOut(boolean lightsOut, boolean animate, boolean force)165     private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) {
166         if (!force && lightsOut == mLightsOut) return;
167 
168         mLightsOut = lightsOut;
169         if (mNavButtons == null) return;
170 
171         // ok, everyone, stop it right there
172         mNavButtons.animate().cancel();
173 
174         // Bump percentage by 10% if dark.
175         float darkBump = mLightTransitionsController.getCurrentDarkIntensity() / 10;
176         final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f;
177 
178         if (!animate) {
179             mNavButtons.setAlpha(navButtonsAlpha);
180         } else {
181             final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
182             mNavButtons.animate()
183                 .alpha(navButtonsAlpha)
184                 .setDuration(duration)
185                 .start();
186         }
187     }
188 
reapplyDarkIntensity()189     public void reapplyDarkIntensity() {
190         applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
191     }
192 
193     @Override
applyDarkIntensity(float darkIntensity)194     public void applyDarkIntensity(float darkIntensity) {
195         SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
196         for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
197             buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
198         }
199         mView.getRotationButtonController().setDarkIntensity(darkIntensity);
200 
201         for (DarkIntensityListener listener : mDarkIntensityListeners) {
202             listener.onDarkIntensity(darkIntensity);
203         }
204         if (mAutoDim) {
205             applyLightsOut(false, true);
206         }
207     }
208 
209     @Override
getTintAnimationDuration()210     public int getTintAnimationDuration() {
211         if (isGesturalModeOnDefaultDisplay(mView.getContext(), mNavBarMode)) {
212             return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME);
213         }
214         return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
215     }
216 
onNavigationModeChanged(int mode)217     public void onNavigationModeChanged(int mode) {
218         mNavBarMode = mode;
219     }
220 
221     /**
222      * Register {@code listener} to be notified when the color of nav bar elements changes.
223      *
224      * Returns the current nav bar color.
225      */
addDarkIntensityListener(DarkIntensityListener listener)226     public float addDarkIntensityListener(DarkIntensityListener listener) {
227         mDarkIntensityListeners.add(listener);
228         return mLightTransitionsController.getCurrentDarkIntensity();
229     }
230 
231     /**
232      * Remove {@code listener} from being notified when the color of nav bar elements changes.
233      */
removeDarkIntensityListener(DarkIntensityListener listener)234     public void removeDarkIntensityListener(DarkIntensityListener listener) {
235         mDarkIntensityListeners.remove(listener);
236     }
237 
dump(PrintWriter pw)238     public void dump(PrintWriter pw) {
239         pw.println("NavigationBarTransitions:");
240         pw.println("  mMode: " + getMode());
241         pw.println("  mAlwaysOpaque: " + isAlwaysOpaque());
242         pw.println("  mAllowAutoDimWallpaperNotVisible: " + mAllowAutoDimWallpaperNotVisible);
243         pw.println("  mWallpaperVisible: " + mWallpaperVisible);
244         pw.println("  mLightsOut: " + mLightsOut);
245         pw.println("  mAutoDim: " + mAutoDim);
246         pw.println("  bg overrideAlpha: " + mBarBackground.getOverrideAlpha());
247         pw.println("  bg color: " + mBarBackground.getColor());
248         pw.println("  bg frame: " + mBarBackground.getFrame());
249     }
250 }
251