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
17package com.android.systemui.statusbar.phone;
18
19import android.content.Context;
20import android.os.Handler;
21import android.os.RemoteException;
22import android.os.ServiceManager;
23import android.util.SparseArray;
24import android.view.Display;
25import android.view.IWallpaperVisibilityListener;
26import android.view.IWindowManager;
27import android.view.MotionEvent;
28import android.view.View;
29import android.view.View.OnLayoutChangeListener;
30
31import com.android.internal.statusbar.IStatusBarService;
32import com.android.systemui.Dependency;
33import com.android.systemui.R;
34
35public 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
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
85    public void init() {
86        applyModeBackground(-1, getMode(), false /*animate*/);
87        applyLightsOut(false /*animate*/, true /*force*/);
88    }
89
90    @Override
91    public void setAutoDim(boolean autoDim) {
92        if (mAutoDim == autoDim) return;
93        mAutoDim = autoDim;
94        applyLightsOut(true, false);
95    }
96
97    @Override
98    protected boolean isLightsOut(int mode) {
99        return super.isLightsOut(mode) || (mAllowAutoDimWallpaperNotVisible && mAutoDim
100                && !mWallpaperVisible && mode != MODE_WARNING);
101    }
102
103    public LightBarTransitionsController getLightTransitionsController() {
104        return mLightTransitionsController;
105    }
106
107    @Override
108    protected void onTransition(int oldMode, int newMode, boolean animate) {
109        super.onTransition(oldMode, newMode, animate);
110        applyLightsOut(animate, false /*force*/);
111    }
112
113    private void applyLightsOut(boolean animate, boolean force) {
114        // apply to lights out
115        applyLightsOut(isLightsOut(getMode()), animate, force);
116    }
117
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
142    public void reapplyDarkIntensity() {
143        applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
144    }
145
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