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 17 package com.android.systemui.statusbar.car; 18 19 import android.app.ActivityManager; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.graphics.PixelFormat; 25 import android.util.Log; 26 import android.view.View; 27 import android.view.ViewGroup.LayoutParams; 28 import android.view.ViewStub; 29 import android.view.WindowManager; 30 import com.android.systemui.BatteryMeterView; 31 import com.android.systemui.R; 32 import com.android.systemui.recents.Recents; 33 import com.android.systemui.recents.misc.SystemServicesProxy; 34 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener; 35 import com.android.systemui.statusbar.StatusBarState; 36 import com.android.systemui.statusbar.phone.PhoneStatusBar; 37 import com.android.systemui.statusbar.phone.PhoneStatusBarView; 38 import com.android.systemui.statusbar.policy.BatteryController; 39 40 /** 41 * A status bar (and navigation bar) tailored for the automotive use case. 42 */ 43 public 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 start()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 destroy()67 public void destroy() { 68 mCarBatteryController.stopListening(); 69 super.destroy(); 70 } 71 72 @Override makeStatusBarView()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 createBatteryController()90 protected BatteryController createBatteryController() { 91 mCarBatteryController = new CarBatteryController(mContext); 92 mCarBatteryController.addBatteryViewHandler(this); 93 return mCarBatteryController; 94 } 95 96 @Override addNavigationBar()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 createNavigationBarView(Context context)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 showBatteryView()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 hideBatteryView()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 registerPackageChangeReceivers()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 repositionNavigationBar()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 onTaskStackChanged()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 createUserSwitcher()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 userSwitched(int newUserId)197 public void userSwitched(int newUserId) { 198 super.userSwitched(newUserId); 199 if (mFullscreenUserSwitcher != null) { 200 mFullscreenUserSwitcher.onUserSwitched(newUserId); 201 } 202 } 203 204 @Override updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked)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