1/*
2 * Copyright (C) 2015 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.car;
18
19import android.app.ActivityManager;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.graphics.PixelFormat;
25import android.util.Log;
26import android.view.View;
27import android.view.ViewGroup.LayoutParams;
28import android.view.ViewStub;
29import android.view.WindowManager;
30import com.android.systemui.BatteryMeterView;
31import com.android.systemui.R;
32import com.android.systemui.recents.Recents;
33import com.android.systemui.recents.misc.SystemServicesProxy;
34import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
35import com.android.systemui.statusbar.StatusBarState;
36import com.android.systemui.statusbar.phone.PhoneStatusBar;
37import com.android.systemui.statusbar.phone.PhoneStatusBarView;
38import com.android.systemui.statusbar.policy.BatteryController;
39
40/**
41 * A status bar (and navigation bar) tailored for the automotive use case.
42 */
43public class CarStatusBar extends PhoneStatusBar implements
44        CarBatteryController.BatteryViewHandler {
45    private static final String TAG = "CarStatusBar";
46
47    private TaskStackListenerImpl mTaskStackListener;
48
49    private CarNavigationBarView mCarNavigationBar;
50    private CarNavigationBarController mController;
51    private FullscreenUserSwitcher mFullscreenUserSwitcher;
52
53    private CarBatteryController mCarBatteryController;
54    private BatteryMeterView mBatteryMeterView;
55
56    @Override
57    public void start() {
58        super.start();
59        mTaskStackListener = new TaskStackListenerImpl();
60        SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
61        registerPackageChangeReceivers();
62
63        mCarBatteryController.startListening();
64    }
65
66    @Override
67    public void destroy() {
68        mCarBatteryController.stopListening();
69        super.destroy();
70    }
71
72    @Override
73    protected PhoneStatusBarView makeStatusBarView() {
74        PhoneStatusBarView statusBarView = super.makeStatusBarView();
75
76        mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
77
78        // By default, the BatteryMeterView should not be visible. It will be toggled visible
79        // when a device has connected by bluetooth.
80        mBatteryMeterView.setVisibility(View.GONE);
81
82        if (Log.isLoggable(TAG, Log.DEBUG)) {
83            Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
84        }
85
86        return statusBarView;
87    }
88
89    @Override
90    protected BatteryController createBatteryController() {
91        mCarBatteryController = new CarBatteryController(mContext);
92        mCarBatteryController.addBatteryViewHandler(this);
93        return mCarBatteryController;
94    }
95
96    @Override
97    protected void addNavigationBar() {
98        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
99                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
100                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
101                WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
102                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
103                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
104                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
105                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
106                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
107                PixelFormat.TRANSLUCENT);
108        lp.setTitle("CarNavigationBar");
109        lp.windowAnimations = 0;
110        mWindowManager.addView(mNavigationBarView, lp);
111    }
112
113    @Override
114    protected void createNavigationBarView(Context context) {
115        if (mNavigationBarView != null) {
116            return;
117        }
118        mCarNavigationBar =
119                (CarNavigationBarView) View.inflate(context, R.layout.car_navigation_bar, null);
120        mController = new CarNavigationBarController(context, mCarNavigationBar,
121                this /* ActivityStarter*/);
122        mNavigationBarView = mCarNavigationBar;
123
124    }
125
126    @Override
127    public void showBatteryView() {
128        if (Log.isLoggable(TAG, Log.DEBUG)) {
129            Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
130        }
131
132        if (mBatteryMeterView != null) {
133            mBatteryMeterView.setVisibility(View.VISIBLE);
134        }
135    }
136
137    @Override
138    public void hideBatteryView() {
139        if (Log.isLoggable(TAG, Log.DEBUG)) {
140            Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
141        }
142
143        if (mBatteryMeterView != null) {
144            mBatteryMeterView.setVisibility(View.GONE);
145        }
146    }
147
148    private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
149        @Override
150        public void onReceive(Context context, Intent intent) {
151            if (intent.getData() == null || mController == null) {
152                return;
153            }
154            String packageName = intent.getData().getSchemeSpecificPart();
155            mController.onPackageChange(packageName);
156        }
157    };
158
159    private void registerPackageChangeReceivers() {
160        IntentFilter filter = new IntentFilter();
161        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
162        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
163        filter.addDataScheme("package");
164        mContext.registerReceiver(mPackageChangeReceiver, filter);
165    }
166
167    @Override
168    protected void repositionNavigationBar() {
169        // The navigation bar for a vehicle will not need to be repositioned, as it is always
170        // set at the bottom.
171    }
172
173    /**
174     * An implementation of TaskStackListener, that listens for changes in the system task
175     * stack and notifies the navigation bar.
176     */
177    private class TaskStackListenerImpl extends TaskStackListener {
178        @Override
179        public void onTaskStackChanged() {
180            SystemServicesProxy ssp = Recents.getSystemServices();
181            ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
182            mController.taskChanged(runningTaskInfo.baseActivity.getPackageName());
183        }
184    }
185
186    @Override
187    protected void createUserSwitcher() {
188        if (mUserSwitcherController.useFullscreenUserSwitcher()) {
189            mFullscreenUserSwitcher = new FullscreenUserSwitcher(this, mUserSwitcherController,
190                    (ViewStub) mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
191        } else {
192            super.createUserSwitcher();
193        }
194    }
195
196    @Override
197    public void userSwitched(int newUserId) {
198        super.userSwitched(newUserId);
199        if (mFullscreenUserSwitcher != null) {
200            mFullscreenUserSwitcher.onUserSwitched(newUserId);
201        }
202    }
203
204    @Override
205    public void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
206        super.updateKeyguardState(goingToFullShade, fromShadeLocked);
207        if (mFullscreenUserSwitcher != null) {
208            if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
209                mFullscreenUserSwitcher.show();
210            } else {
211                mFullscreenUserSwitcher.hide();
212            }
213        }
214    }
215}
216