blob: 7adb36d615d1ac43136fe58914606de54798da2d [file] [log] [blame]
Rakesh Iyer1186faa2015-12-07 16:48:46 -08001/*
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
Victor Chan1c6d0582016-01-09 16:26:37 -080019import android.app.ActivityManager;
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080020import android.app.ActivityOptions;
Rakesh Iyer9f831f62016-02-16 20:06:22 -080021import android.content.BroadcastReceiver;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080022import android.content.Context;
Rakesh Iyer9f831f62016-02-16 20:06:22 -080023import android.content.Intent;
24import android.content.IntentFilter;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080025import android.graphics.PixelFormat;
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080026import android.os.Bundle;
Victor Chan1c6d0582016-01-09 16:26:37 -080027import android.os.Handler;
28import android.os.Looper;
Jorim Jaggi2adba072016-03-03 13:43:39 +010029import android.os.RemoteException;
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080030import android.os.UserHandle;
31import android.util.Log;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080032import android.view.View;
33import android.view.ViewGroup.LayoutParams;
Rakesh Iyer2790a372016-01-22 15:33:39 -080034import android.view.ViewStub;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080035import android.view.WindowManager;
Anthony Chen1c59e9f2016-04-11 11:05:48 -070036import android.widget.LinearLayout;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070037import com.android.systemui.BatteryMeterView;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080038import com.android.systemui.R;
Victor Chan1c6d0582016-01-09 16:26:37 -080039import com.android.systemui.recents.Recents;
40import com.android.systemui.recents.misc.SystemServicesProxy;
Jaewan Kim938a50b2016-03-14 17:35:43 +090041import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
Rakesh Iyer2790a372016-01-22 15:33:39 -080042import com.android.systemui.statusbar.StatusBarState;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080043import com.android.systemui.statusbar.phone.PhoneStatusBar;
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080044import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070045import com.android.systemui.statusbar.phone.PhoneStatusBarView;
46import com.android.systemui.statusbar.policy.BatteryController;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080047
48/**
49 * A status bar (and navigation bar) tailored for the automotive use case.
50 */
Anthony Chenda62fdcd52016-04-06 16:15:14 -070051public class CarStatusBar extends PhoneStatusBar implements
52 CarBatteryController.BatteryViewHandler {
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080053 private static final String TAG = "CarStatusBar";
54
55 private SystemServicesProxy mSystemServicesProxy;
Victor Chan1c6d0582016-01-09 16:26:37 -080056 private TaskStackListenerImpl mTaskStackListener;
Victor Chan1c6d0582016-01-09 16:26:37 -080057
58 private CarNavigationBarView mCarNavigationBar;
59 private CarNavigationBarController mController;
Rakesh Iyer2790a372016-01-22 15:33:39 -080060 private FullscreenUserSwitcher mFullscreenUserSwitcher;
Victor Chan1c6d0582016-01-09 16:26:37 -080061
Anthony Chenda62fdcd52016-04-06 16:15:14 -070062 private CarBatteryController mCarBatteryController;
63 private BatteryMeterView mBatteryMeterView;
64
Anthony Chen1c59e9f2016-04-11 11:05:48 -070065 private ConnectedDeviceSignalController mConnectedDeviceSignalController;
66 private View mSignalsView;
Jason Monk49fa0162017-01-11 09:21:56 -050067 private CarNavigationBarView mNavigationBarView;
Anthony Chen1c59e9f2016-04-11 11:05:48 -070068
Victor Chan1c6d0582016-01-09 16:26:37 -080069 @Override
70 public void start() {
71 super.start();
Jaewan Kim938a50b2016-03-14 17:35:43 +090072 mTaskStackListener = new TaskStackListenerImpl();
73 SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
Rakesh Iyer9f831f62016-02-16 20:06:22 -080074 registerPackageChangeReceivers();
Anthony Chenda62fdcd52016-04-06 16:15:14 -070075
76 mCarBatteryController.startListening();
Anthony Chen1c59e9f2016-04-11 11:05:48 -070077 mConnectedDeviceSignalController.startListening();
Anthony Chenda62fdcd52016-04-06 16:15:14 -070078 }
79
80 @Override
81 public void destroy() {
82 mCarBatteryController.stopListening();
Anthony Chen1c59e9f2016-04-11 11:05:48 -070083 mConnectedDeviceSignalController.stopListening();
84
Anthony Chenda62fdcd52016-04-06 16:15:14 -070085 super.destroy();
86 }
87
88 @Override
89 protected PhoneStatusBarView makeStatusBarView() {
90 PhoneStatusBarView statusBarView = super.makeStatusBarView();
91
92 mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
93
94 // By default, the BatteryMeterView should not be visible. It will be toggled visible
95 // when a device has connected by bluetooth.
96 mBatteryMeterView.setVisibility(View.GONE);
97
Anthony Chen1c59e9f2016-04-11 11:05:48 -070098 ViewStub stub = (ViewStub) statusBarView.findViewById(R.id.connected_device_signals_stub);
99 mSignalsView = stub.inflate();
100
101 // When a ViewStub if inflated, it does not respect the margins on the inflated view.
102 // As a result, manually add the ending margin.
103 ((LinearLayout.LayoutParams) mSignalsView.getLayoutParams()).setMarginEnd(
104 mContext.getResources().getDimensionPixelOffset(
105 R.dimen.status_bar_connected_device_signal_margin_end));
106
107 mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
Anthony Chen13e1b672016-09-26 11:01:05 -0700108 mSignalsView, mBluetoothController);
Anthony Chen1c59e9f2016-04-11 11:05:48 -0700109
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700110 if (Log.isLoggable(TAG, Log.DEBUG)) {
111 Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
112 }
113
114 return statusBarView;
115 }
116
117 @Override
118 protected BatteryController createBatteryController() {
119 mCarBatteryController = new CarBatteryController(mContext);
120 mCarBatteryController.addBatteryViewHandler(this);
121 return mCarBatteryController;
Victor Chan1c6d0582016-01-09 16:26:37 -0800122 }
123
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800124 @Override
Jason Monk49fa0162017-01-11 09:21:56 -0500125 protected void createNavigationBar() {
126 if (mNavigationBarView != null) {
127 return;
128 }
129
130 mCarNavigationBar =
131 (CarNavigationBarView) View.inflate(mContext, R.layout.car_navigation_bar, null);
132 mController = new CarNavigationBarController(mContext, mCarNavigationBar,
133 this /* ActivityStarter*/);
134 mNavigationBarView = mCarNavigationBar;
135 mCarNavigationBar.getBarTransitions().setAlwaysOpaque(true);
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800136 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
137 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
138 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
Victor Chan1c6d0582016-01-09 16:26:37 -0800139 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
140 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
141 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
142 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
143 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
144 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800145 PixelFormat.TRANSLUCENT);
146 lp.setTitle("CarNavigationBar");
147 lp.windowAnimations = 0;
148 mWindowManager.addView(mNavigationBarView, lp);
149 }
150
151 @Override
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700152 public void showBatteryView() {
153 if (Log.isLoggable(TAG, Log.DEBUG)) {
154 Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
155 }
156
157 if (mBatteryMeterView != null) {
158 mBatteryMeterView.setVisibility(View.VISIBLE);
159 }
160 }
161
162 @Override
163 public void hideBatteryView() {
164 if (Log.isLoggable(TAG, Log.DEBUG)) {
165 Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
166 }
167
168 if (mBatteryMeterView != null) {
169 mBatteryMeterView.setVisibility(View.GONE);
170 }
171 }
172
Rakesh Iyer9f831f62016-02-16 20:06:22 -0800173 private BroadcastReceiver mPackageChangeReceiver = new BroadcastReceiver() {
174 @Override
175 public void onReceive(Context context, Intent intent) {
176 if (intent.getData() == null || mController == null) {
177 return;
178 }
179 String packageName = intent.getData().getSchemeSpecificPart();
180 mController.onPackageChange(packageName);
181 }
182 };
183
184 private void registerPackageChangeReceivers() {
185 IntentFilter filter = new IntentFilter();
186 filter.addAction(Intent.ACTION_PACKAGE_ADDED);
187 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
188 filter.addDataScheme("package");
189 mContext.registerReceiver(mPackageChangeReceiver, filter);
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800190 }
Victor Chanecdb8b02016-01-07 18:32:43 -0800191
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800192 public boolean hasDockedTask() {
193 return Recents.getSystemServices().hasDockedTask();
194 }
195
Victor Chan1c6d0582016-01-09 16:26:37 -0800196 /**
Jaewan Kim938a50b2016-03-14 17:35:43 +0900197 * An implementation of TaskStackListener, that listens for changes in the system task
Victor Chan1c6d0582016-01-09 16:26:37 -0800198 * stack and notifies the navigation bar.
199 */
Jaewan Kim938a50b2016-03-14 17:35:43 +0900200 private class TaskStackListenerImpl extends TaskStackListener {
Wale Ogunwale480dca02016-02-06 13:58:29 -0800201 @Override
Victor Chan1c6d0582016-01-09 16:26:37 -0800202 public void onTaskStackChanged() {
Victor Chan1c6d0582016-01-09 16:26:37 -0800203 SystemServicesProxy ssp = Recents.getSystemServices();
Winsond46b7272016-04-20 11:54:27 -0700204 ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800205 if (runningTaskInfo != null && runningTaskInfo.baseActivity != null) {
Rakesh Iyer02ee8852016-05-05 16:02:21 -0700206 mController.taskChanged(runningTaskInfo.baseActivity.getPackageName(),
207 runningTaskInfo.stackId);
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800208 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800209 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800210 }
Rakesh Iyer2790a372016-01-22 15:33:39 -0800211
212 @Override
213 protected void createUserSwitcher() {
214 if (mUserSwitcherController.useFullscreenUserSwitcher()) {
215 mFullscreenUserSwitcher = new FullscreenUserSwitcher(this, mUserSwitcherController,
216 (ViewStub) mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub));
217 } else {
218 super.createUserSwitcher();
219 }
220 }
221
222 @Override
223 public void userSwitched(int newUserId) {
224 super.userSwitched(newUserId);
225 if (mFullscreenUserSwitcher != null) {
226 mFullscreenUserSwitcher.onUserSwitched(newUserId);
227 }
228 }
229
230 @Override
231 public void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
232 super.updateKeyguardState(goingToFullShade, fromShadeLocked);
233 if (mFullscreenUserSwitcher != null) {
234 if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
235 mFullscreenUserSwitcher.show();
236 } else {
237 mFullscreenUserSwitcher.hide();
238 }
239 }
240 }
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800241
Victor Chanc87554c2016-08-24 14:58:14 -0700242 @Override
243 public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
244 // Do nothing, we don't want to display media art in the lock screen for a car.
245 }
246
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800247 private int startActivityWithOptions(Intent intent, Bundle options) {
248 int result = ActivityManager.START_CANCELED;
249 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800250 result = ActivityManager.getService().startActivityAsUser(null /* caller */,
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800251 mContext.getBasePackageName(),
252 intent,
253 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
254 null /* resultTo*/,
255 null /* resultWho*/,
256 0 /* requestCode*/,
257 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP,
258 null /* profilerInfo*/,
259 options,
260 UserHandle.CURRENT.getIdentifier());
261 } catch (RemoteException e) {
262 Log.w(TAG, "Unable to start activity", e);
263 }
264
265 return result;
266 }
267
268 public int startActivityOnStack(Intent intent, int stackId) {
269 ActivityOptions options = ActivityOptions.makeBasic();
270 options.setLaunchStackId(stackId);
271 return startActivityWithOptions(intent, options.toBundle());
272 }
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800273}