blob: 23cc0fc51ec03cd9701c49b46326b3f7282cbad7 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.phone;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME;
import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.SparseArray;
import android.view.Display;
import android.view.IWallpaperVisibilityListener;
import android.view.IWindowManager;
import android.view.View;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.List;
public final class NavigationBarTransitions extends BarTransitions implements
LightBarTransitionsController.DarkIntensityApplier {
/**
* Notified when the color of nav bar elements changes.
*/
public interface DarkIntensityListener {
/**
* Called when the color of nav bar elements changes.
* @param darkIntensity 0 is the lightest color, 1 is the darkest.
*/
void onDarkIntensity(float darkIntensity);
}
private final NavigationBarView mView;
private final IStatusBarService mBarService;
private final LightBarTransitionsController mLightTransitionsController;
private final boolean mAllowAutoDimWallpaperNotVisible;
private boolean mWallpaperVisible;
private boolean mLightsOut;
private boolean mAutoDim;
private View mNavButtons;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private List<DarkIntensityListener> mDarkIntensityListeners;
private final Handler mHandler = Handler.getMain();
private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
new IWallpaperVisibilityListener.Stub() {
@Override
public void onWallpaperVisibilityChanged(boolean newVisibility,
int displayId) throws RemoteException {
mWallpaperVisible = newVisibility;
mHandler.post(() -> applyLightsOut(true, false));
}
};
public NavigationBarTransitions(NavigationBarView view) {
super(view, R.drawable.nav_background);
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mLightTransitionsController = new LightBarTransitionsController(view.getContext(), this);
mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
mDarkIntensityListeners = new ArrayList();
IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
try {
mWallpaperVisible = windowManagerService.registerWallpaperVisibilityListener(
mWallpaperVisibilityListener, Display.DEFAULT_DISPLAY);
} catch (RemoteException e) {
}
mView.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
View currentView = mView.getCurrentView();
if (currentView != null) {
mNavButtons = currentView.findViewById(R.id.nav_buttons);
applyLightsOut(false, true);
}
});
View currentView = mView.getCurrentView();
if (currentView != null) {
mNavButtons = currentView.findViewById(R.id.nav_buttons);
}
}
public void init() {
applyModeBackground(-1, getMode(), false /*animate*/);
applyLightsOut(false /*animate*/, true /*force*/);
}
@Override
public void destroy() {
IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
try {
windowManagerService.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
Display.DEFAULT_DISPLAY);
} catch (RemoteException e) {
}
}
@Override
public void setAutoDim(boolean autoDim) {
// Ensure we aren't in gestural nav if we are triggering auto dim
if (autoDim && NavBarTintController.isEnabled(mView.getContext(), mNavBarMode)) return;
if (mAutoDim == autoDim) return;
mAutoDim = autoDim;
applyLightsOut(true, false);
}
void setBackgroundFrame(Rect frame) {
mBarBackground.setFrame(frame);
}
@Override
protected boolean isLightsOut(int mode) {
return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim
&& !mWallpaperVisible && mode != MODE_WARNING);
}
public LightBarTransitionsController getLightTransitionsController() {
return mLightTransitionsController;
}
@Override
protected void onTransition(int oldMode, int newMode, boolean animate) {
super.onTransition(oldMode, newMode, animate);
applyLightsOut(animate, false /*force*/);
mView.onBarTransition(newMode);
}
private void applyLightsOut(boolean animate, boolean force) {
// apply to lights out
applyLightsOut(isLightsOut(getMode()), animate, force);
}
private void applyLightsOut(boolean lightsOut, boolean animate, boolean force) {
if (!force && lightsOut == mLightsOut) return;
mLightsOut = lightsOut;
if (mNavButtons == null) return;
// ok, everyone, stop it right there
mNavButtons.animate().cancel();
// Bump percentage by 10% if dark.
float darkBump = mLightTransitionsController.getCurrentDarkIntensity() / 10;
final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f;
if (!animate) {
mNavButtons.setAlpha(navButtonsAlpha);
} else {
final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
mNavButtons.animate()
.alpha(navButtonsAlpha)
.setDuration(duration)
.start();
}
}
public void reapplyDarkIntensity() {
applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
}
@Override
public void applyDarkIntensity(float darkIntensity) {
SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
mView.getRotationButtonController().setDarkIntensity(darkIntensity);
for (DarkIntensityListener listener : mDarkIntensityListeners) {
listener.onDarkIntensity(darkIntensity);
}
if (mAutoDim) {
applyLightsOut(false, true);
}
}
@Override
public int getTintAnimationDuration() {
if (NavBarTintController.isEnabled(mView.getContext(), mNavBarMode)) {
return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME);
}
return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
}
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
}
/**
* Register {@code listener} to be notified when the color of nav bar elements changes.
*
* Returns the current nav bar color.
*/
public float addDarkIntensityListener(DarkIntensityListener listener) {
mDarkIntensityListeners.add(listener);
return mLightTransitionsController.getCurrentDarkIntensity();
}
/**
* Remove {@code listener} from being notified when the color of nav bar elements changes.
*/
public void removeDarkIntensityListener(DarkIntensityListener listener) {
mDarkIntensityListeners.remove(listener);
}
}