1 /* 2 * Copyright (C) 2013 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.phone; 18 19 import android.content.Context; 20 import android.os.Handler; 21 import android.os.RemoteException; 22 import android.os.ServiceManager; 23 import android.util.SparseArray; 24 import android.view.Display; 25 import android.view.IWallpaperVisibilityListener; 26 import android.view.IWindowManager; 27 import android.view.MotionEvent; 28 import android.view.View; 29 import android.view.View.OnLayoutChangeListener; 30 31 import com.android.internal.statusbar.IStatusBarService; 32 import com.android.systemui.Dependency; 33 import com.android.systemui.R; 34 35 public final class NavigationBarTransitions extends BarTransitions { 36 37 private final NavigationBarView mView; 38 private final IStatusBarService mBarService; 39 private final LightBarTransitionsController mLightTransitionsController; 40 private final boolean mAllowAutoDimWallpaperNotVisible; 41 private boolean mWallpaperVisible; 42 43 private boolean mLightsOut; 44 private boolean mAutoDim; 45 private View mNavButtons; 46 NavigationBarTransitions(NavigationBarView view)47 public NavigationBarTransitions(NavigationBarView view) { 48 super(view, R.drawable.nav_background); 49 mView = view; 50 mBarService = IStatusBarService.Stub.asInterface( 51 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 52 mLightTransitionsController = new LightBarTransitionsController(view.getContext(), 53 this::applyDarkIntensity); 54 mAllowAutoDimWallpaperNotVisible = view.getContext().getResources() 55 .getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper); 56 57 IWindowManager windowManagerService = Dependency.get(IWindowManager.class); 58 Handler handler = Handler.getMain(); 59 try { 60 mWallpaperVisible = windowManagerService.registerWallpaperVisibilityListener( 61 new IWallpaperVisibilityListener.Stub() { 62 @Override 63 public void onWallpaperVisibilityChanged(boolean newVisibility, 64 int displayId) throws RemoteException { 65 mWallpaperVisible = newVisibility; 66 handler.post(() -> applyLightsOut(true, false)); 67 } 68 }, Display.DEFAULT_DISPLAY); 69 } catch (RemoteException e) { 70 } 71 mView.addOnLayoutChangeListener( 72 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { 73 View currentView = mView.getCurrentView(); 74 if (currentView != null) { 75 mNavButtons = currentView.findViewById(R.id.nav_buttons); 76 applyLightsOut(false, true); 77 } 78 }); 79 View currentView = mView.getCurrentView(); 80 if (currentView != null) { 81 mNavButtons = currentView.findViewById(R.id.nav_buttons); 82 } 83 } 84 init()85 public void init() { 86 applyModeBackground(-1, getMode(), false /*animate*/); 87 applyLightsOut(false /*animate*/, true /*force*/); 88 } 89 90 @Override setAutoDim(boolean autoDim)91 public void setAutoDim(boolean autoDim) { 92 if (mAutoDim == autoDim) return; 93 mAutoDim = autoDim; 94 applyLightsOut(true, false); 95 } 96 97 @Override isLightsOut(int mode)98 protected boolean isLightsOut(int mode) { 99 return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim 100 && !mWallpaperVisible && mode != MODE_WARNING); 101 } 102 getLightTransitionsController()103 public LightBarTransitionsController getLightTransitionsController() { 104 return mLightTransitionsController; 105 } 106 107 @Override onTransition(int oldMode, int newMode, boolean animate)108 protected void onTransition(int oldMode, int newMode, boolean animate) { 109 super.onTransition(oldMode, newMode, animate); 110 applyLightsOut(animate, false /*force*/); 111 } 112 applyLightsOut(boolean animate, boolean force)113 private void applyLightsOut(boolean animate, boolean force) { 114 // apply to lights out 115 applyLightsOut(isLightsOut(getMode()), animate, force); 116 } 117 applyLightsOut(boolean lightsOut, boolean animate, boolean force)118 private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) { 119 if (!force && lightsOut == mLightsOut) return; 120 121 mLightsOut = lightsOut; 122 if (mNavButtons == null) return; 123 124 // ok, everyone, stop it right there 125 mNavButtons.animate().cancel(); 126 127 // Bump percentage by 10% if dark. 128 float darkBump = mLightTransitionsController.getCurrentDarkIntensity() / 10; 129 final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f; 130 131 if (!animate) { 132 mNavButtons.setAlpha(navButtonsAlpha); 133 } else { 134 final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION; 135 mNavButtons.animate() 136 .alpha(navButtonsAlpha) 137 .setDuration(duration) 138 .start(); 139 } 140 } 141 reapplyDarkIntensity()142 public void reapplyDarkIntensity() { 143 applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity()); 144 } 145 applyDarkIntensity(float darkIntensity)146 public void applyDarkIntensity(float darkIntensity) { 147 SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers(); 148 for (int i = buttonDispatchers.size() - 1; i >= 0; i--) { 149 buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity); 150 } 151 if (mAutoDim) { 152 applyLightsOut(false, true); 153 } 154 mView.onDarkIntensityChange(darkIntensity); 155 } 156 157 private final View.OnTouchListener mLightsOutListener = new View.OnTouchListener() { 158 @Override 159 public boolean onTouch(View v, MotionEvent ev) { 160 if (ev.getAction() == MotionEvent.ACTION_DOWN) { 161 // even though setting the systemUI visibility below will turn these views 162 // on, we need them to come up faster so that they can catch this motion 163 // event 164 applyLightsOut(false, false, false); 165 166 try { 167 mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE, 168 "LightsOutListener"); 169 } catch (android.os.RemoteException ex) { 170 } 171 } 172 return false; 173 } 174 }; 175 } 176