Advertisement
csphelps76

Untitled

Feb 12th, 2013
41
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 67.85 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2010 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.tablet;
  18.  
  19. import android.animation.LayoutTransition;
  20. import android.animation.ObjectAnimator;
  21. import android.app.ActivityManager;
  22. import android.app.ActivityManagerNative;
  23. import android.app.Notification;
  24. import android.app.PendingIntent;
  25. import android.app.StatusBarManager;
  26. import android.content.BroadcastReceiver;
  27. import android.content.ContentResolver;
  28. import android.content.Context;
  29. import android.content.Intent;
  30. import android.content.IntentFilter;
  31. import android.content.SharedPreferences;
  32. import android.content.res.Configuration;
  33. import android.content.res.CustomTheme;
  34. import android.content.res.Resources;
  35. import android.graphics.PixelFormat;
  36. import android.graphics.Point;
  37. import android.graphics.drawable.Drawable;
  38. import android.graphics.drawable.LayerDrawable;
  39. import android.inputmethodservice.InputMethodService;
  40. import android.os.IBinder;
  41. import android.os.Message;
  42. import android.os.RemoteException;
  43. import android.os.ServiceManager;
  44. import android.provider.Settings;
  45. import android.text.TextUtils;
  46. import android.util.Pair;
  47. import android.util.Slog;
  48. import android.view.Display;
  49. import android.view.Gravity;
  50. import android.view.KeyEvent;
  51. import android.view.MotionEvent;
  52. import android.view.SoundEffectConstants;
  53. import android.view.VelocityTracker;
  54. import android.view.View;
  55. import android.view.ViewConfiguration;
  56. import android.view.ViewGroup;
  57. import android.view.ViewGroup.LayoutParams;
  58. import android.view.WindowManager;
  59. import android.view.accessibility.AccessibilityEvent;
  60. import android.widget.ImageView;
  61. import android.widget.FrameLayout;
  62. import android.widget.LinearLayout;
  63. import android.widget.ScrollView;
  64. import android.widget.TextView;
  65.  
  66. import com.android.internal.statusbar.StatusBarIcon;
  67. import com.android.internal.statusbar.StatusBarNotification;
  68. import com.android.systemui.R;
  69. import com.android.systemui.statusbar.BaseStatusBar;
  70. import com.android.systemui.statusbar.CommandQueue;
  71. import com.android.systemui.statusbar.DoNotDisturb;
  72. import com.android.systemui.statusbar.NotificationData;
  73. import com.android.systemui.statusbar.NotificationData.Entry;
  74. import com.android.systemui.statusbar.SignalClusterView;
  75. import com.android.systemui.statusbar.StatusBarIconView;
  76. import com.android.systemui.statusbar.policy.CenterClock;
  77. import com.android.systemui.statusbar.policy.Clock;
  78. import com.android.systemui.statusbar.policy.BatteryController;
  79. import com.android.systemui.statusbar.policy.BluetoothController;
  80. import com.android.systemui.statusbar.policy.CompatModeButton;
  81. import com.android.systemui.statusbar.policy.LocationController;
  82. import com.android.systemui.statusbar.policy.NetworkController;
  83. import com.android.systemui.statusbar.policy.NotificationRowLayout;
  84. import com.android.systemui.statusbar.policy.Prefs;
  85.  
  86. import java.io.FileDescriptor;
  87. import java.io.PrintWriter;
  88. import java.util.ArrayList;
  89.  
  90. public class TabletStatusBar extends BaseStatusBar implements
  91. InputMethodsPanel.OnHardKeyboardEnabledChangeListener {
  92. public static final boolean DEBUG = false;
  93. public static final boolean DEBUG_COMPAT_HELP = false;
  94. public static final String TAG = "TabletStatusBar";
  95.  
  96.  
  97. public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
  98. public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
  99. public static final int MSG_OPEN_NOTIFICATION_PEEK = 1002;
  100. public static final int MSG_CLOSE_NOTIFICATION_PEEK = 1003;
  101. // 1020-1029 reserved for BaseStatusBar
  102. public static final int MSG_SHOW_CHROME = 1030;
  103. public static final int MSG_HIDE_CHROME = 1031;
  104. public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
  105. public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
  106. public static final int MSG_OPEN_COMPAT_MODE_PANEL = 1050;
  107. public static final int MSG_CLOSE_COMPAT_MODE_PANEL = 1051;
  108. public static final int MSG_STOP_TICKER = 2000;
  109.  
  110. // Fitts' Law assistance for LatinIME; see policy.EventHole
  111. private static final boolean FAKE_SPACE_BAR = true;
  112.  
  113. // Notification "peeking" (flyover preview of individual notifications)
  114. final static int NOTIFICATION_PEEK_HOLD_THRESH = 200; // ms
  115. final static int NOTIFICATION_PEEK_FADE_DELAY = 3000; // ms
  116.  
  117. private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
  118. private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
  119.  
  120. // The height of the bar, as definied by the build. It may be taller if we're plugged
  121. // into hdmi.
  122. int mNaturalBarHeight = -1;
  123. int mIconSize = -1;
  124. int mIconHPadding = -1;
  125. int mNavIconWidth = -1;
  126. int mMenuNavIconWidth = -1;
  127. private int mMaxNotificationIcons = 5;
  128.  
  129. TabletStatusBarView mStatusBarView;
  130. View mNotificationArea;
  131. View mNotificationTrigger;
  132. NotificationIconArea mNotificationIconArea;
  133. ViewGroup mNavigationArea;
  134.  
  135. boolean mNotificationDNDMode;
  136. NotificationData.Entry mNotificationDNDDummyEntry;
  137.  
  138. ImageView mBackButton;
  139. View mHomeButton;
  140. View mMenuButton;
  141. View mRecentButton;
  142. private boolean mAltBackButtonEnabledForIme;
  143.  
  144. ViewGroup mFeedbackIconArea; // notification icons, IME icon, compat icon
  145. InputMethodButton mInputMethodSwitchButton;
  146. CompatModeButton mCompatModeButton;
  147.  
  148. NotificationPanel mNotificationPanel;
  149. WindowManager.LayoutParams mNotificationPanelParams;
  150. NotificationPeekPanel mNotificationPeekWindow;
  151. ViewGroup mNotificationPeekRow;
  152. int mNotificationPeekIndex;
  153. IBinder mNotificationPeekKey;
  154. LayoutTransition mNotificationPeekScrubLeft, mNotificationPeekScrubRight;
  155.  
  156. int mNotificationPeekTapDuration;
  157. int mNotificationFlingVelocity;
  158.  
  159. BatteryController mBatteryController;
  160. BluetoothController mBluetoothController;
  161. LocationController mLocationController;
  162. NetworkController mNetworkController;
  163. DoNotDisturb mDoNotDisturb;
  164.  
  165. ViewGroup mBarContents;
  166.  
  167. // hide system chrome ("lights out") support
  168. View mShadow;
  169.  
  170. NotificationIconArea.IconLayout mIconLayout;
  171.  
  172. TabletTicker mTicker;
  173.  
  174. View mFakeSpaceBar;
  175. KeyEvent mSpaceBarKeyEvent = null;
  176.  
  177. View mCompatibilityHelpDialog = null;
  178.  
  179. // for disabling the status bar
  180. int mDisabled = 0;
  181.  
  182. private InputMethodsPanel mInputMethodsPanel;
  183. private CompatModePanel mCompatModePanel;
  184.  
  185. // clock
  186. private int mClockStyle;
  187.  
  188. private int mSystemUiVisibility = 0;
  189.  
  190. private int mNavigationIconHints = 0;
  191.  
  192. private int mShowSearchHoldoff = 0;
  193.  
  194. public Context getContext() { return mContext; }
  195.  
  196. private Runnable mShowSearchPanel = new Runnable() {
  197. public void run() {
  198. showSearchPanel();
  199. }
  200. };
  201.  
  202. private View.OnTouchListener mHomeSearchActionListener = new View.OnTouchListener() {
  203. public boolean onTouch(View v, MotionEvent event) {
  204. switch(event.getAction()) {
  205. case MotionEvent.ACTION_DOWN:
  206. if (!shouldDisableNavbarGestures() && !inKeyguardRestrictedInputMode()) {
  207. mHandler.removeCallbacks(mShowSearchPanel);
  208. mHandler.postDelayed(mShowSearchPanel, mShowSearchHoldoff);
  209. }
  210. break;
  211.  
  212. case MotionEvent.ACTION_UP:
  213. case MotionEvent.ACTION_CANCEL:
  214. mHandler.removeCallbacks(mShowSearchPanel);
  215. break;
  216. }
  217. return false;
  218. }
  219. };
  220.  
  221. @Override
  222. protected void createAndAddWindows() {
  223. addStatusBarWindow();
  224. addPanelWindows();
  225. }
  226.  
  227. private void addStatusBarWindow() {
  228. final View sb = makeStatusBarView();
  229.  
  230. final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
  231. ViewGroup.LayoutParams.MATCH_PARENT,
  232. ViewGroup.LayoutParams.MATCH_PARENT,
  233. WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
  234. WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
  235. | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
  236. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
  237. PixelFormat.OPAQUE);
  238.  
  239. // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags. The status bar occupies
  240. // very little screen real-estate and is updated fairly frequently. By using CPU rendering
  241. // for the status bar, we prevent the GPU from having to wake up just to do these small
  242. // updates, which should help keep power consumption down.
  243.  
  244. lp.gravity = getStatusBarGravity();
  245. lp.setTitle("SystemBar");
  246. lp.packageName = mContext.getPackageName();
  247. mWindowManager.addView(sb, lp);
  248. }
  249.  
  250. // last theme that was applied in order to detect theme change (as opposed
  251. // to some other configuration change).
  252. CustomTheme mCurrentTheme;
  253. private boolean mRecreating = false;
  254.  
  255.  
  256. protected void addPanelWindows() {
  257. final Context context = mContext;
  258. final Resources res = mContext.getResources();
  259.  
  260. // Notification Panel
  261. mNotificationPanel = (NotificationPanel)View.inflate(context,
  262. R.layout.system_bar_notification_panel, null);
  263. mNotificationPanel.setBar(this);
  264. mNotificationPanel.show(false, false);
  265. mNotificationPanel.setOnTouchListener(
  266. new TouchOutsideListener(MSG_CLOSE_NOTIFICATION_PANEL, mNotificationPanel));
  267.  
  268. // the battery icon
  269. mBatteryController.addIconView((ImageView)mNotificationPanel.findViewById(R.id.battery));
  270. mBatteryController.addLabelView(
  271. (TextView)mNotificationPanel.findViewById(R.id.battery_text));
  272.  
  273. // Bt
  274. mBluetoothController.addIconView(
  275. (ImageView)mNotificationPanel.findViewById(R.id.bluetooth));
  276.  
  277. // network icons: either a combo icon that switches between mobile and data, or distinct
  278. // mobile and data icons
  279. final ImageView mobileRSSI =
  280. (ImageView)mNotificationPanel.findViewById(R.id.mobile_signal);
  281. if (mobileRSSI != null) {
  282. mNetworkController.addPhoneSignalIconView(mobileRSSI);
  283. }
  284. final ImageView wifiRSSI =
  285. (ImageView)mNotificationPanel.findViewById(R.id.wifi_signal);
  286. if (wifiRSSI != null) {
  287. mNetworkController.addWifiIconView(wifiRSSI);
  288. }
  289. mNetworkController.addWifiLabelView(
  290. (TextView)mNotificationPanel.findViewById(R.id.wifi_text));
  291.  
  292. mNetworkController.addDataTypeIconView(
  293. (ImageView)mNotificationPanel.findViewById(R.id.mobile_type));
  294. mNetworkController.addMobileLabelView(
  295. (TextView)mNotificationPanel.findViewById(R.id.mobile_text));
  296. mNetworkController.addCombinedLabelView(
  297. (TextView)mBarContents.findViewById(R.id.network_text));
  298.  
  299. mStatusBarView.setIgnoreChildren(0, mNotificationTrigger, mNotificationPanel);
  300.  
  301. WindowManager.LayoutParams lp = mNotificationPanelParams = new WindowManager.LayoutParams(
  302. res.getDimensionPixelSize(R.dimen.notification_panel_width),
  303. getNotificationPanelHeight(),
  304. WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
  305. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  306. | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
  307. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
  308. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
  309. | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
  310. PixelFormat.TRANSLUCENT);
  311. lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
  312. lp.setTitle("NotificationPanel");
  313. lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
  314. | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
  315. lp.windowAnimations = com.android.internal.R.style.Animation; // == no animation
  316. // lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
  317.  
  318. mWindowManager.addView(mNotificationPanel, lp);
  319.  
  320. // Search Panel
  321. mStatusBarView.setBar(this);
  322. mHomeButton.setOnTouchListener(mHomeSearchActionListener);
  323. updateSearchPanel();
  324.  
  325. // Input methods Panel
  326. mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
  327. R.layout.system_bar_input_methods_panel, null);
  328. mInputMethodsPanel.setHardKeyboardEnabledChangeListener(this);
  329. mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
  330. MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
  331. mInputMethodsPanel.setImeSwitchButton(mInputMethodSwitchButton);
  332. mStatusBarView.setIgnoreChildren(2, mInputMethodSwitchButton, mInputMethodsPanel);
  333. lp = new WindowManager.LayoutParams(
  334. ViewGroup.LayoutParams.WRAP_CONTENT,
  335. ViewGroup.LayoutParams.WRAP_CONTENT,
  336. WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
  337. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  338. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
  339. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
  340. | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
  341. PixelFormat.TRANSLUCENT);
  342. lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
  343. lp.setTitle("InputMethodsPanel");
  344. lp.windowAnimations = R.style.Animation_RecentPanel;
  345.  
  346. mWindowManager.addView(mInputMethodsPanel, lp);
  347.  
  348. // Compatibility mode selector panel
  349. mCompatModePanel = (CompatModePanel) View.inflate(context,
  350. R.layout.system_bar_compat_mode_panel, null);
  351. mCompatModePanel.setOnTouchListener(new TouchOutsideListener(
  352. MSG_CLOSE_COMPAT_MODE_PANEL, mCompatModePanel));
  353. mCompatModePanel.setTrigger(mCompatModeButton);
  354. mCompatModePanel.setVisibility(View.GONE);
  355. mStatusBarView.setIgnoreChildren(3, mCompatModeButton, mCompatModePanel);
  356. lp = new WindowManager.LayoutParams(
  357. 250,
  358. ViewGroup.LayoutParams.WRAP_CONTENT,
  359. WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
  360. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  361. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
  362. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
  363. | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
  364. PixelFormat.TRANSLUCENT);
  365. lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
  366. lp.setTitle("CompatModePanel");
  367. lp.windowAnimations = android.R.style.Animation_Dialog;
  368.  
  369. mWindowManager.addView(mCompatModePanel, lp);
  370.  
  371. mRecentButton.setOnTouchListener(mRecentsPreloadOnTouchListener);
  372.  
  373. mPile = (NotificationRowLayout)mNotificationPanel.findViewById(R.id.content);
  374. mPile.removeAllViews();
  375. mPile.setLongPressListener(getNotificationLongClicker());
  376.  
  377. ScrollView scroller = (ScrollView)mPile.getParent();
  378. scroller.setFillViewport(true);
  379. }
  380.  
  381. @Override
  382. protected int getExpandedViewMaxHeight() {
  383. return getNotificationPanelHeight();
  384. }
  385.  
  386. private int getNotificationPanelHeight() {
  387. final Resources res = mContext.getResources();
  388. final Display d = mWindowManager.getDefaultDisplay();
  389. final Point size = new Point();
  390. d.getRealSize(size);
  391. return Math.max(res.getDimensionPixelSize(R.dimen.notification_panel_min_height), size.y);
  392. }
  393.  
  394. @Override
  395. public void start() {
  396. super.start(); // will add the main bar view
  397. }
  398.  
  399. private static void copyNotifications(ArrayList<Pair<IBinder, StatusBarNotification>> dest,
  400. NotificationData source) {
  401. int N = source.size();
  402. for (int i = 0; i < N; i++) {
  403. NotificationData.Entry entry = source.get(i);
  404. dest.add(Pair.create(entry.key, entry.notification));
  405. }
  406. }
  407.  
  408. private void recreateStatusBar() {
  409. mRecreating = true;
  410. mStatusBarContainer.removeAllViews();
  411.  
  412. // extract notifications.
  413. int nNotifs = mNotificationData.size();
  414. ArrayList<Pair<IBinder, StatusBarNotification>> notifications =
  415. new ArrayList<Pair<IBinder, StatusBarNotification>>(nNotifs);
  416. copyNotifications(notifications, mNotificationData);
  417. mNotificationData.clear();
  418.  
  419. mStatusBarContainer.addView(makeStatusBarView());
  420.  
  421. // recreate notifications.
  422. for (int i = 0; i < nNotifs; i++) {
  423. Pair<IBinder, StatusBarNotification> notifData = notifications.get(i);
  424. addNotificationViews(notifData.first, notifData.second);
  425. }
  426.  
  427. setAreThereNotifications();
  428.  
  429. mRecreating = false;
  430. }
  431.  
  432.  
  433. @Override
  434. protected void onConfigurationChanged(Configuration newConfig) {
  435. // detect theme change.
  436. CustomTheme newTheme = mContext.getResources().getConfiguration().customTheme;
  437. if (newTheme != null &&
  438. (mCurrentTheme == null || !mCurrentTheme.equals(newTheme))) {
  439. mCurrentTheme = (CustomTheme)newTheme.clone();
  440. recreateStatusBar();
  441. }
  442. loadDimens();
  443. mNotificationPanelParams.height = getNotificationPanelHeight();
  444. mWindowManager.updateViewLayout(mNotificationPanel, mNotificationPanelParams);
  445. mShowSearchHoldoff = mContext.getResources().getInteger(
  446. R.integer.config_show_search_delay);
  447. updateSearchPanel();
  448. }
  449.  
  450. protected void loadDimens() {
  451. final Resources res = mContext.getResources();
  452.  
  453. mNaturalBarHeight = res.getDimensionPixelSize(
  454. com.android.internal.R.dimen.navigation_bar_height);
  455.  
  456. int newIconSize = res.getDimensionPixelSize(
  457. com.android.internal.R.dimen.system_bar_icon_size);
  458. int newIconHPadding = res.getDimensionPixelSize(
  459. R.dimen.status_bar_icon_padding);
  460. int newNavIconWidth = res.getDimensionPixelSize(R.dimen.navigation_key_width);
  461. int newMenuNavIconWidth = res.getDimensionPixelSize(R.dimen.navigation_menu_key_width);
  462.  
  463. if (mNavigationArea != null && newNavIconWidth != mNavIconWidth) {
  464. mNavIconWidth = newNavIconWidth;
  465.  
  466. LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
  467. mNavIconWidth, ViewGroup.LayoutParams.MATCH_PARENT);
  468. mBackButton.setLayoutParams(lp);
  469. mHomeButton.setLayoutParams(lp);
  470. mRecentButton.setLayoutParams(lp);
  471. }
  472.  
  473. if (mNavigationArea != null && newMenuNavIconWidth != mMenuNavIconWidth) {
  474. mMenuNavIconWidth = newMenuNavIconWidth;
  475.  
  476. LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
  477. mMenuNavIconWidth, ViewGroup.LayoutParams.MATCH_PARENT);
  478. mMenuButton.setLayoutParams(lp);
  479. }
  480.  
  481. if (newIconHPadding != mIconHPadding || newIconSize != mIconSize) {
  482. // Slog.d(TAG, "size=" + newIconSize + " padding=" + newIconHPadding);
  483. mIconHPadding = newIconHPadding;
  484. mIconSize = newIconSize;
  485. reloadAllNotificationIcons(); // reload the tray
  486. }
  487.  
  488. final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
  489. if (numIcons != mMaxNotificationIcons) {
  490. mMaxNotificationIcons = numIcons;
  491. if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
  492. reloadAllNotificationIcons();
  493. }
  494. }
  495.  
  496. @Override
  497. public View getStatusBarView() {
  498. return mStatusBarView;
  499. }
  500.  
  501. protected View makeStatusBarView() {
  502. final Context context = mContext;
  503.  
  504. CustomTheme currentTheme = mContext.getResources().getConfiguration().customTheme;
  505. if (currentTheme != null) {
  506. mCurrentTheme = (CustomTheme)currentTheme.clone();
  507. }
  508.  
  509. loadDimens();
  510.  
  511. final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
  512. context, R.layout.system_bar, null);
  513. mStatusBarView = sb;
  514.  
  515. sb.setHandler(mHandler);
  516.  
  517. try {
  518. // Sanity-check that someone hasn't set up the config wrong and asked for a navigation
  519. // bar on a tablet that has only the system bar
  520. if (mWindowManagerService.hasNavigationBar()) {
  521. Slog.e(TAG, "Tablet device cannot show navigation bar and system bar");
  522. }
  523. } catch (RemoteException ex) {
  524. }
  525.  
  526. mBarContents = (ViewGroup) sb.findViewById(R.id.bar_contents);
  527.  
  528. // the whole right-hand side of the bar
  529. mNotificationArea = sb.findViewById(R.id.notificationArea);
  530. mNotificationArea.setOnTouchListener(new NotificationTriggerTouchListener());
  531.  
  532. // the button to open the notification area
  533. mNotificationTrigger = sb.findViewById(R.id.notificationTrigger);
  534.  
  535. // the more notifications icon
  536. mNotificationIconArea = (NotificationIconArea)sb.findViewById(R.id.notificationIcons);
  537.  
  538. // where the icons go
  539. mIconLayout = (NotificationIconArea.IconLayout) sb.findViewById(R.id.icons);
  540.  
  541. mNotificationPeekTapDuration = ViewConfiguration.getTapTimeout();
  542. mNotificationFlingVelocity = 300; // px/s
  543.  
  544. mTicker = new TabletTicker(this);
  545.  
  546. // The icons
  547. mLocationController = new LocationController(mContext); // will post a notification
  548.  
  549. // watch the PREF_DO_NOT_DISTURB and convert to appropriate disable() calls
  550. mDoNotDisturb = new DoNotDisturb(mContext);
  551.  
  552. mBatteryController = new BatteryController(mContext);
  553. mBatteryController.addIconView((ImageView)sb.findViewById(R.id.battery));
  554. mBluetoothController = new BluetoothController(mContext);
  555. mBluetoothController.addIconView((ImageView)sb.findViewById(R.id.bluetooth));
  556.  
  557. mNetworkController = new NetworkController(mContext);
  558. final SignalClusterView signalCluster =
  559. (SignalClusterView)sb.findViewById(R.id.signal_cluster);
  560. mNetworkController.addSignalCluster(signalCluster);
  561.  
  562. // The navigation buttons
  563. mBackButton = (ImageView)sb.findViewById(R.id.back);
  564. mNavigationArea = (ViewGroup) sb.findViewById(R.id.navigationArea);
  565. mHomeButton = mNavigationArea.findViewById(R.id.home);
  566. mMenuButton = mNavigationArea.findViewById(R.id.menu);
  567. mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
  568. mRecentButton.setOnClickListener(mOnClickListener);
  569.  
  570. LayoutTransition lt = new LayoutTransition();
  571. lt.setDuration(250);
  572. // don't wait for these transitions; we just want icons to fade in/out, not move around
  573. lt.setDuration(LayoutTransition.CHANGE_APPEARING, 0);
  574. lt.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 0);
  575. lt.addTransitionListener(new LayoutTransition.TransitionListener() {
  576. public void endTransition(LayoutTransition transition, ViewGroup container,
  577. View view, int transitionType) {
  578. // ensure the menu button doesn't stick around on the status bar after it's been
  579. // removed
  580. mBarContents.invalidate();
  581. }
  582. public void startTransition(LayoutTransition transition, ViewGroup container,
  583. View view, int transitionType) {}
  584. });
  585. mNavigationArea.setLayoutTransition(lt);
  586. // no multi-touch on the nav buttons
  587. mNavigationArea.setMotionEventSplittingEnabled(false);
  588.  
  589. // The bar contents buttons
  590. mFeedbackIconArea = (ViewGroup)sb.findViewById(R.id.feedbackIconArea);
  591. mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
  592. // Overwrite the lister
  593. mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
  594.  
  595. mCompatModeButton = (CompatModeButton) sb.findViewById(R.id.compatModeButton);
  596. mCompatModeButton.setOnClickListener(mOnClickListener);
  597. mCompatModeButton.setVisibility(View.GONE);
  598.  
  599. // for redirecting errant bar taps to the IME
  600. mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
  601.  
  602. // "shadows" of the status bar features, for lights-out mode
  603. mShadow = sb.findViewById(R.id.bar_shadow);
  604. mShadow.setOnTouchListener(
  605. new View.OnTouchListener() {
  606. public boolean onTouch(View v, MotionEvent ev) {
  607. if (ev.getAction() == MotionEvent.ACTION_DOWN) {
  608. // even though setting the systemUI visibility below will turn these views
  609. // on, we need them to come up faster so that they can catch this motion
  610. // event
  611. mShadow.setVisibility(View.GONE);
  612. mBarContents.setVisibility(View.VISIBLE);
  613.  
  614. try {
  615. mBarService.setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
  616. } catch (RemoteException ex) {
  617. // system process dead
  618. }
  619. }
  620. return false;
  621. }
  622. });
  623.  
  624. // tuning parameters
  625. final int LIGHTS_GOING_OUT_SYSBAR_DURATION = 750;
  626. final int LIGHTS_GOING_OUT_SHADOW_DURATION = 750;
  627. final int LIGHTS_GOING_OUT_SHADOW_DELAY = 0;
  628.  
  629. final int LIGHTS_COMING_UP_SYSBAR_DURATION = 200;
  630. // final int LIGHTS_COMING_UP_SYSBAR_DELAY = 50;
  631. final int LIGHTS_COMING_UP_SHADOW_DURATION = 0;
  632.  
  633. LayoutTransition xition = new LayoutTransition();
  634. xition.setAnimator(LayoutTransition.APPEARING,
  635. ObjectAnimator.ofFloat(null, "alpha", 0.5f, 1f));
  636. xition.setDuration(LayoutTransition.APPEARING, LIGHTS_COMING_UP_SYSBAR_DURATION);
  637. xition.setStartDelay(LayoutTransition.APPEARING, 0);
  638. xition.setAnimator(LayoutTransition.DISAPPEARING,
  639. ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
  640. xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_GOING_OUT_SYSBAR_DURATION);
  641. xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
  642. ((ViewGroup)sb.findViewById(R.id.bar_contents_holder)).setLayoutTransition(xition);
  643.  
  644. xition = new LayoutTransition();
  645. xition.setAnimator(LayoutTransition.APPEARING,
  646. ObjectAnimator.ofFloat(null, "alpha", 0f, 1f));
  647. xition.setDuration(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DURATION);
  648. xition.setStartDelay(LayoutTransition.APPEARING, LIGHTS_GOING_OUT_SHADOW_DELAY);
  649. xition.setAnimator(LayoutTransition.DISAPPEARING,
  650. ObjectAnimator.ofFloat(null, "alpha", 1f, 0f));
  651. xition.setDuration(LayoutTransition.DISAPPEARING, LIGHTS_COMING_UP_SHADOW_DURATION);
  652. xition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
  653. ((ViewGroup)sb.findViewById(R.id.bar_shadow_holder)).setLayoutTransition(xition);
  654.  
  655. // set the initial view visibility
  656. setAreThereNotifications();
  657.  
  658. // receive broadcasts
  659. IntentFilter filter = new IntentFilter();
  660. filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
  661. filter.addAction(Intent.ACTION_SCREEN_OFF);
  662. context.registerReceiver(mBroadcastReceiver, filter);
  663.  
  664. return sb;
  665. }
  666.  
  667. @Override
  668. protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
  669. WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
  670. (int) mContext.getResources().getDimension(R.dimen.status_bar_recents_width),
  671. ViewGroup.LayoutParams.MATCH_PARENT,
  672. WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
  673. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  674. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
  675. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
  676. | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
  677. PixelFormat.TRANSLUCENT);
  678. lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
  679. lp.setTitle("RecentsPanel");
  680. lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
  681. lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
  682. | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
  683.  
  684. return lp;
  685. }
  686.  
  687. @Override
  688. protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
  689. boolean opaque = false;
  690. WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
  691. LayoutParams.MATCH_PARENT,
  692. LayoutParams.MATCH_PARENT,
  693. WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
  694. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  695. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
  696. | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
  697. (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
  698. if (ActivityManager.isHighEndGfx()) {
  699. lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
  700. } else {
  701. lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
  702. lp.dimAmount = 0.7f;
  703. }
  704. lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
  705. lp.setTitle("SearchPanel");
  706. // TODO: Define custom animation for Search panel
  707. lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
  708. lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
  709. | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
  710. return lp;
  711. }
  712.  
  713. @Override
  714. public void toggleNotificationShade() {
  715. int msg = (mNotificationPanel.isShowing())
  716. ? MSG_CLOSE_NOTIFICATION_PANEL : MSG_OPEN_NOTIFICATION_PANEL;
  717. mHandler.removeMessages(msg);
  718. mHandler.sendEmptyMessage(msg);
  719. }
  720.  
  721. @Override
  722. protected void updateSearchPanel() {
  723. super.updateSearchPanel();
  724. mSearchPanelView.setStatusBarView(mStatusBarView);
  725. mStatusBarView.setDelegateView(mSearchPanelView);
  726. }
  727.  
  728. @Override
  729. public void showSearchPanel() {
  730. super.showSearchPanel();
  731. WindowManager.LayoutParams lp =
  732. (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
  733. lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
  734. mWindowManager.updateViewLayout(mStatusBarView, lp);
  735. }
  736.  
  737. @Override
  738. public void hideSearchPanel() {
  739. super.hideSearchPanel();
  740. WindowManager.LayoutParams lp =
  741. (android.view.WindowManager.LayoutParams) mStatusBarView.getLayoutParams();
  742. lp.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
  743. mWindowManager.updateViewLayout(mStatusBarView, lp);
  744. }
  745.  
  746. @Override
  747. protected void onBarTouchEvent(MotionEvent ev) {
  748. }
  749.  
  750. @Override
  751. protected void showBar(boolean showSearch){
  752. }
  753.  
  754. @Override
  755. protected void setSearchLightOn(boolean on){
  756. }
  757.  
  758. public int getStatusBarHeight() {
  759. return mStatusBarView != null ? mStatusBarView.getHeight()
  760. : mContext.getResources().getDimensionPixelSize(
  761. com.android.internal.R.dimen.navigation_bar_height);
  762. }
  763.  
  764. protected int getStatusBarGravity() {
  765. return Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
  766. }
  767.  
  768. public void onBarHeightChanged(int height) {
  769. final WindowManager.LayoutParams lp
  770. = (WindowManager.LayoutParams)mStatusBarView.getLayoutParams();
  771. if (lp == null) {
  772. // haven't been added yet
  773. return;
  774. }
  775. if (lp.height != height) {
  776. lp.height = height;
  777. mWindowManager.updateViewLayout(mStatusBarView, lp);
  778. }
  779. }
  780.  
  781. @Override
  782. protected BaseStatusBar.H createHandler() {
  783. return new TabletStatusBar.H();
  784. }
  785.  
  786. private class H extends BaseStatusBar.H {
  787. public void handleMessage(Message m) {
  788. super.handleMessage(m);
  789. switch (m.what) {
  790. case MSG_OPEN_NOTIFICATION_PEEK:
  791. if (DEBUG) Slog.d(TAG, "opening notification peek window; arg=" + m.arg1);
  792.  
  793. if (m.arg1 >= 0) {
  794. final int N = mNotificationData.size();
  795.  
  796. if (!mNotificationDNDMode) {
  797. if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
  798. NotificationData.Entry entry = mNotificationData.get(N-1-mNotificationPeekIndex);
  799. entry.icon.setBackgroundColor(0);
  800. mNotificationPeekIndex = -1;
  801. mNotificationPeekKey = null;
  802. }
  803. }
  804.  
  805. final int peekIndex = m.arg1;
  806. if (peekIndex < N) {
  807. //Slog.d(TAG, "loading peek: " + peekIndex);
  808. NotificationData.Entry entry =
  809. mNotificationDNDMode
  810. ? mNotificationDNDDummyEntry
  811. : mNotificationData.get(N-1-peekIndex);
  812. NotificationData.Entry copy = new NotificationData.Entry(
  813. entry.key,
  814. entry.notification,
  815. entry.icon);
  816. inflateViews(copy, mNotificationPeekRow);
  817.  
  818. if (mNotificationDNDMode) {
  819. copy.content.setOnClickListener(new View.OnClickListener() {
  820. public void onClick(View v) {
  821. SharedPreferences.Editor editor = Prefs.edit(mContext);
  822. editor.putBoolean(Prefs.DO_NOT_DISTURB_PREF, false);
  823. editor.apply();
  824. animateCollapsePanels();
  825. visibilityChanged(false);
  826. }
  827. });
  828. }
  829.  
  830. entry.icon.setBackgroundColor(0x20FFFFFF);
  831.  
  832. // mNotificationPeekRow.setLayoutTransition(
  833. // peekIndex < mNotificationPeekIndex
  834. // ? mNotificationPeekScrubLeft
  835. // : mNotificationPeekScrubRight);
  836.  
  837. mNotificationPeekRow.removeAllViews();
  838. mNotificationPeekRow.addView(copy.row);
  839.  
  840. mNotificationPeekWindow.setVisibility(View.VISIBLE);
  841. mNotificationPanel.show(false, true);
  842.  
  843. mNotificationPeekIndex = peekIndex;
  844. mNotificationPeekKey = entry.key;
  845. }
  846. }
  847. break;
  848. case MSG_CLOSE_NOTIFICATION_PEEK:
  849. if (DEBUG) Slog.d(TAG, "closing notification peek window");
  850. mNotificationPeekWindow.setVisibility(View.GONE);
  851. mNotificationPeekRow.removeAllViews();
  852.  
  853. final int N = mNotificationData.size();
  854. if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) {
  855. NotificationData.Entry entry =
  856. mNotificationDNDMode
  857. ? mNotificationDNDDummyEntry
  858. : mNotificationData.get(N-1-mNotificationPeekIndex);
  859. entry.icon.setBackgroundColor(0);
  860. }
  861.  
  862. mNotificationPeekIndex = -1;
  863. mNotificationPeekKey = null;
  864. break;
  865. case MSG_OPEN_NOTIFICATION_PANEL:
  866. if (DEBUG) Slog.d(TAG, "opening notifications panel");
  867. if (!mNotificationPanel.isShowing()) {
  868. mNotificationPanel.show(true, true);
  869. mNotificationArea.setVisibility(View.INVISIBLE);
  870. mTicker.halt();
  871. }
  872. break;
  873. case MSG_CLOSE_NOTIFICATION_PANEL:
  874. if (DEBUG) Slog.d(TAG, "closing notifications panel");
  875. if (mNotificationPanel.isShowing()) {
  876. mNotificationPanel.show(false, true);
  877. mNotificationArea.setVisibility(View.VISIBLE);
  878. }
  879. break;
  880. case MSG_OPEN_INPUT_METHODS_PANEL:
  881. if (DEBUG) Slog.d(TAG, "opening input methods panel");
  882. if (mInputMethodsPanel != null) mInputMethodsPanel.openPanel();
  883. break;
  884. case MSG_CLOSE_INPUT_METHODS_PANEL:
  885. if (DEBUG) Slog.d(TAG, "closing input methods panel");
  886. if (mInputMethodsPanel != null) mInputMethodsPanel.closePanel(false);
  887. break;
  888. case MSG_OPEN_COMPAT_MODE_PANEL:
  889. if (DEBUG) Slog.d(TAG, "opening compat panel");
  890. if (mCompatModePanel != null) mCompatModePanel.openPanel();
  891. break;
  892. case MSG_CLOSE_COMPAT_MODE_PANEL:
  893. if (DEBUG) Slog.d(TAG, "closing compat panel");
  894. if (mCompatModePanel != null) mCompatModePanel.closePanel();
  895. break;
  896. case MSG_SHOW_CHROME:
  897. if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
  898. mBarContents.setVisibility(View.VISIBLE);
  899. mShadow.setVisibility(View.GONE);
  900. mSystemUiVisibility &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
  901. notifyUiVisibilityChanged();
  902. break;
  903. case MSG_HIDE_CHROME:
  904. if (DEBUG) Slog.d(TAG, "showing shadows (lights out)");
  905. animateCollapsePanels();
  906. visibilityChanged(false);
  907. mBarContents.setVisibility(View.GONE);
  908. mShadow.setVisibility(View.VISIBLE);
  909. mSystemUiVisibility |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
  910. notifyUiVisibilityChanged();
  911. break;
  912. case MSG_STOP_TICKER:
  913. mTicker.halt();
  914. break;
  915. }
  916. }
  917. }
  918.  
  919. public void addIcon(String slot, int index, int viewIndex, StatusBarIcon icon) {
  920. if (DEBUG) Slog.d(TAG, "addIcon(" + slot + ") -> " + icon);
  921. }
  922.  
  923. public void updateIcon(String slot, int index, int viewIndex,
  924. StatusBarIcon old, StatusBarIcon icon) {
  925. if (DEBUG) Slog.d(TAG, "updateIcon(" + slot + ") -> " + icon);
  926. }
  927.  
  928. public void removeIcon(String slot, int index, int viewIndex) {
  929. if (DEBUG) Slog.d(TAG, "removeIcon(" + slot + ")");
  930. }
  931.  
  932. public void addNotification(IBinder key, StatusBarNotification notification) {
  933. if (DEBUG) Slog.d(TAG, "addNotification(" + key + " -> " + notification + ")");
  934. addNotificationViews(key, notification);
  935.  
  936. final boolean immersive = isImmersive();
  937. if (false && immersive) {
  938. // TODO: immersive mode popups for tablet
  939. } else if (notification.notification.fullScreenIntent != null) {
  940. // not immersive & a full-screen alert should be shown
  941. Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
  942. + " sending fullScreenIntent");
  943. try {
  944. notification.notification.fullScreenIntent.send();
  945. } catch (PendingIntent.CanceledException e) {
  946. }
  947. } else if (!mRecreating) {
  948. tick(key, notification, true);
  949. }
  950.  
  951. setAreThereNotifications();
  952. }
  953.  
  954. public void removeNotification(IBinder key) {
  955. if (DEBUG) Slog.d(TAG, "removeNotification(" + key + ")");
  956. removeNotificationViews(key);
  957. mTicker.remove(key);
  958. setAreThereNotifications();
  959. }
  960.  
  961. public void showClock(boolean show) {
  962. ContentResolver resolver = mContext.getContentResolver();
  963. Clock clock = (Clock) mBarContents.findViewById(R.id.clock);
  964. CenterClock cclock = (CenterClock) mBarContents.findViewById(R.id.center_clock);
  965. View network_text = mBarContents.findViewById(R.id.network_text);
  966. mClockStyle = Settings.System.getInt(resolver,
  967. Settings.System.STATUS_BAR_CLOCK_STYLE, 1);
  968. if (mClockStyle != 0 && clock != null && cclock != null) {
  969. clock.updateClockVisibility(show);
  970. cclock.updateClockVisibility(show);
  971. }
  972. else{
  973. clock.updateClockVisibility(false);
  974. cclock.updateClockVisibility(false);
  975. }
  976. if (network_text != null) {
  977. network_text.setVisibility((!show) ? View.VISIBLE : View.GONE);
  978. }
  979. }
  980.  
  981. public void disable(int state) {
  982. int old = mDisabled;
  983. int diff = state ^ old;
  984. mDisabled = state;
  985.  
  986. // act accordingly
  987. if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
  988. boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
  989. Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
  990. showClock(show);
  991. }
  992. if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
  993. boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
  994. Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
  995. mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
  996. }
  997. if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
  998. if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
  999. Slog.i(TAG, "DISABLE_EXPAND: yes");
  1000. animateCollapsePanels();
  1001. visibilityChanged(false);
  1002. }
  1003. }
  1004. if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
  1005. mNotificationDNDMode = Prefs.read(mContext)
  1006. .getBoolean(Prefs.DO_NOT_DISTURB_PREF, Prefs.DO_NOT_DISTURB_DEFAULT);
  1007.  
  1008. if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
  1009. Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes" + (mNotificationDNDMode?" (DND)":""));
  1010. mTicker.halt();
  1011. } else {
  1012. Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no" + (mNotificationDNDMode?" (DND)":""));
  1013. }
  1014.  
  1015. // refresh icons to show either notifications or the DND message
  1016. reloadAllNotificationIcons();
  1017. } else if ((diff & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
  1018. if ((state & StatusBarManager.DISABLE_NOTIFICATION_TICKER) != 0) {
  1019. mTicker.halt();
  1020. }
  1021. }
  1022. if ((diff & (StatusBarManager.DISABLE_RECENT
  1023. | StatusBarManager.DISABLE_BACK
  1024. | StatusBarManager.DISABLE_HOME)) != 0) {
  1025. setNavigationVisibility(state);
  1026.  
  1027. if ((state & StatusBarManager.DISABLE_RECENT) != 0) {
  1028. // close recents if it's visible
  1029. mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
  1030. mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
  1031. }
  1032. }
  1033. }
  1034.  
  1035. private void setNavigationVisibility(int visibility) {
  1036. boolean disableHome = ((visibility & StatusBarManager.DISABLE_HOME) != 0);
  1037. boolean disableRecent = ((visibility & StatusBarManager.DISABLE_RECENT) != 0);
  1038. boolean disableBack = ((visibility & StatusBarManager.DISABLE_BACK) != 0);
  1039.  
  1040. mBackButton.setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
  1041. mHomeButton.setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
  1042. mRecentButton.setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
  1043.  
  1044. mInputMethodSwitchButton.setScreenLocked(
  1045. (visibility & StatusBarManager.DISABLE_SYSTEM_INFO) != 0);
  1046. }
  1047.  
  1048. private boolean hasTicker(Notification n) {
  1049. return n.tickerView != null || !TextUtils.isEmpty(n.tickerText);
  1050. }
  1051.  
  1052. @Override
  1053. protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
  1054. // Don't show the ticker when the windowshade is open.
  1055. if (mNotificationPanel.isShowing()) {
  1056. return;
  1057. }
  1058. // If they asked for FLAG_ONLY_ALERT_ONCE, then only show this notification
  1059. // if it's a new notification.
  1060. if (!firstTime && (n.notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0) {
  1061. return;
  1062. }
  1063. // Show the ticker if one is requested. Also don't do this
  1064. // until status bar window is attached to the window manager,
  1065. // because... well, what's the point otherwise? And trying to
  1066. // run a ticker without being attached will crash!
  1067. if (hasTicker(n.notification) && mStatusBarView.getWindowToken() != null) {
  1068. if (0 == (mDisabled & (StatusBarManager.DISABLE_NOTIFICATION_ICONS
  1069. | StatusBarManager.DISABLE_NOTIFICATION_TICKER))) {
  1070. mTicker.add(key, n);
  1071. mFeedbackIconArea.setVisibility(View.GONE);
  1072. }
  1073. }
  1074. }
  1075.  
  1076. // called by TabletTicker when it's done with all queued ticks
  1077. public void doneTicking() {
  1078. mFeedbackIconArea.setVisibility(View.VISIBLE);
  1079. }
  1080.  
  1081. public void animateExpandNotificationsPanel() {
  1082. mHandler.removeMessages(MSG_OPEN_NOTIFICATION_PANEL);
  1083. mHandler.sendEmptyMessage(MSG_OPEN_NOTIFICATION_PANEL);
  1084. }
  1085.  
  1086. public void animateCollapsePanels() {
  1087. animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
  1088. }
  1089.  
  1090. public void animateCollapsePanels(int flags) {
  1091. if ((flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) {
  1092. mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PANEL);
  1093. mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
  1094. }
  1095. if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
  1096. mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
  1097. mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
  1098. }
  1099. if ((flags & CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL) == 0) {
  1100. mHandler.removeMessages(MSG_CLOSE_SEARCH_PANEL);
  1101. mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
  1102. }
  1103. if ((flags & CommandQueue.FLAG_EXCLUDE_INPUT_METHODS_PANEL) == 0) {
  1104. mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
  1105. mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
  1106. }
  1107. if ((flags & CommandQueue.FLAG_EXCLUDE_COMPAT_MODE_PANEL) == 0) {
  1108. mHandler.removeMessages(MSG_CLOSE_COMPAT_MODE_PANEL);
  1109. mHandler.sendEmptyMessage(MSG_CLOSE_COMPAT_MODE_PANEL);
  1110. }
  1111.  
  1112. }
  1113.  
  1114. @Override
  1115. public void animateExpandSettingsPanel() {
  1116. // TODO: Implement when TabletStatusBar begins to be used.
  1117. }
  1118.  
  1119. @Override // CommandQueue
  1120. public void setNavigationIconHints(int hints) {
  1121. if (hints == mNavigationIconHints) return;
  1122.  
  1123. if (DEBUG) {
  1124. android.widget.Toast.makeText(mContext,
  1125. "Navigation icon hints = " + hints,
  1126. 500).show();
  1127. }
  1128.  
  1129. mNavigationIconHints = hints;
  1130.  
  1131. mBackButton.setAlpha(
  1132. (0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_NOP)) ? 0.5f : 1.0f);
  1133. mHomeButton.setAlpha(
  1134. (0 != (hints & StatusBarManager.NAVIGATION_HINT_HOME_NOP)) ? 0.5f : 1.0f);
  1135. mRecentButton.setAlpha(
  1136. (0 != (hints & StatusBarManager.NAVIGATION_HINT_RECENT_NOP)) ? 0.5f : 1.0f);
  1137.  
  1138. mBackButton.setImageResource(
  1139. (0 != (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT))
  1140. ? R.drawable.ic_sysbar_back_ime
  1141. : R.drawable.ic_sysbar_back);
  1142. }
  1143.  
  1144. private void notifyUiVisibilityChanged() {
  1145. try {
  1146. mWindowManagerService.statusBarVisibilityChanged(mSystemUiVisibility);
  1147. } catch (RemoteException ex) {
  1148. }
  1149. }
  1150.  
  1151. @Override // CommandQueue
  1152. public void setSystemUiVisibility(int vis, int mask) {
  1153. final int oldVal = mSystemUiVisibility;
  1154. final int newVal = (oldVal&~mask) | (vis&mask);
  1155. final int diff = newVal ^ oldVal;
  1156.  
  1157. if (diff != 0) {
  1158. mSystemUiVisibility = newVal;
  1159.  
  1160. if (0 != (diff & View.SYSTEM_UI_FLAG_LOW_PROFILE)) {
  1161. mHandler.removeMessages(MSG_HIDE_CHROME);
  1162. mHandler.removeMessages(MSG_SHOW_CHROME);
  1163. mHandler.sendEmptyMessage(0 == (vis & View.SYSTEM_UI_FLAG_LOW_PROFILE)
  1164. ? MSG_SHOW_CHROME : MSG_HIDE_CHROME);
  1165. }
  1166.  
  1167. notifyUiVisibilityChanged();
  1168. }
  1169. }
  1170.  
  1171. public void setLightsOn(boolean on) {
  1172. // Policy note: if the frontmost activity needs the menu key, we assume it is a legacy app
  1173. // that can't handle lights-out mode.
  1174. if (mMenuButton.getVisibility() == View.VISIBLE) {
  1175. on = true;
  1176. }
  1177.  
  1178. Slog.v(TAG, "setLightsOn(" + on + ")");
  1179. if (on) {
  1180. setSystemUiVisibility(0, View.SYSTEM_UI_FLAG_LOW_PROFILE);
  1181. } else {
  1182. setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE, View.SYSTEM_UI_FLAG_LOW_PROFILE);
  1183. }
  1184. }
  1185.  
  1186. public void topAppWindowChanged(boolean showMenu) {
  1187. if (DEBUG) {
  1188. Slog.d(TAG, (showMenu?"showing":"hiding") + " the MENU button");
  1189. }
  1190. mMenuButton.setVisibility(showMenu ? View.VISIBLE : View.GONE);
  1191.  
  1192. // See above re: lights-out policy for legacy apps.
  1193. if (showMenu) setLightsOn(true);
  1194.  
  1195. mCompatModeButton.refresh();
  1196. if (mCompatModeButton.getVisibility() == View.VISIBLE) {
  1197. if (DEBUG_COMPAT_HELP
  1198. || ! Prefs.read(mContext).getBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, false)) {
  1199. showCompatibilityHelp();
  1200. }
  1201. } else {
  1202. hideCompatibilityHelp();
  1203. mCompatModePanel.closePanel();
  1204. }
  1205. }
  1206.  
  1207. private void showCompatibilityHelp() {
  1208. if (mCompatibilityHelpDialog != null) {
  1209. return;
  1210. }
  1211.  
  1212. mCompatibilityHelpDialog = View.inflate(mContext, R.layout.compat_mode_help, null);
  1213. View button = mCompatibilityHelpDialog.findViewById(R.id.button);
  1214.  
  1215. button.setOnClickListener(new View.OnClickListener() {
  1216. @Override
  1217. public void onClick(View v) {
  1218. hideCompatibilityHelp();
  1219. SharedPreferences.Editor editor = Prefs.edit(mContext);
  1220. editor.putBoolean(Prefs.SHOWN_COMPAT_MODE_HELP, true);
  1221. editor.apply();
  1222. }
  1223. });
  1224.  
  1225. WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
  1226. ViewGroup.LayoutParams.MATCH_PARENT,
  1227. ViewGroup.LayoutParams.MATCH_PARENT,
  1228. WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG,
  1229. WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
  1230. | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
  1231. | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
  1232. PixelFormat.TRANSLUCENT);
  1233. lp.setTitle("CompatibilityModeDialog");
  1234. lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
  1235. | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
  1236. lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons; // simple fade
  1237.  
  1238. mWindowManager.addView(mCompatibilityHelpDialog, lp);
  1239. }
  1240.  
  1241. private void hideCompatibilityHelp() {
  1242. if (mCompatibilityHelpDialog != null) {
  1243. mWindowManager.removeView(mCompatibilityHelpDialog);
  1244. mCompatibilityHelpDialog = null;
  1245. }
  1246. }
  1247.  
  1248. public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
  1249. mInputMethodSwitchButton.setImeWindowStatus(token,
  1250. (vis & InputMethodService.IME_ACTIVE) != 0);
  1251. updateNotificationIcons();
  1252. mInputMethodsPanel.setImeToken(token);
  1253.  
  1254. boolean altBack = (backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS)
  1255. || ((vis & InputMethodService.IME_VISIBLE) != 0);
  1256. mAltBackButtonEnabledForIme = altBack;
  1257.  
  1258. mCommandQueue.setNavigationIconHints(
  1259. altBack ? (mNavigationIconHints | StatusBarManager.NAVIGATION_HINT_BACK_ALT)
  1260. : (mNavigationIconHints & ~StatusBarManager.NAVIGATION_HINT_BACK_ALT));
  1261.  
  1262. if (FAKE_SPACE_BAR) {
  1263. mFakeSpaceBar.setVisibility(((vis & InputMethodService.IME_VISIBLE) != 0)
  1264. ? View.VISIBLE : View.GONE);
  1265. }
  1266. }
  1267.  
  1268. @Override
  1269. public void setHardKeyboardStatus(boolean available, boolean enabled) {
  1270. if (DEBUG) {
  1271. Slog.d(TAG, "Set hard keyboard status: available=" + available
  1272. + ", enabled=" + enabled);
  1273. }
  1274. mInputMethodSwitchButton.setHardKeyboardStatus(available);
  1275. updateNotificationIcons();
  1276. mInputMethodsPanel.setHardKeyboardStatus(available, enabled);
  1277. }
  1278.  
  1279. @Override
  1280. public void onHardKeyboardEnabledChange(boolean enabled) {
  1281. try {
  1282. mBarService.setHardKeyboardEnabled(enabled);
  1283. } catch (RemoteException ex) {
  1284. }
  1285. }
  1286.  
  1287. private boolean isImmersive() {
  1288. try {
  1289. return ActivityManagerNative.getDefault().isTopActivityImmersive();
  1290. //Slog.d(TAG, "Top activity is " + (immersive?"immersive":"not immersive"));
  1291. } catch (RemoteException ex) {
  1292. // the end is nigh
  1293. return false;
  1294. }
  1295. }
  1296.  
  1297. @Override
  1298. protected void setAreThereNotifications() {
  1299. if (mNotificationPanel != null) {
  1300. mNotificationPanel.setClearable(isDeviceProvisioned() && mNotificationData.hasClearableItems());
  1301. }
  1302. }
  1303.  
  1304. private View.OnClickListener mOnClickListener = new View.OnClickListener() {
  1305. public void onClick(View v) {
  1306. if (v == mRecentButton) {
  1307. onClickRecentButton();
  1308. } else if (v == mInputMethodSwitchButton) {
  1309. onClickInputMethodSwitchButton();
  1310. } else if (v == mCompatModeButton) {
  1311. onClickCompatModeButton();
  1312. }
  1313. }
  1314. };
  1315.  
  1316. public void onClickRecentButton() {
  1317. if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
  1318. if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
  1319. toggleRecentApps();
  1320. }
  1321. }
  1322.  
  1323. public void onClickInputMethodSwitchButton() {
  1324. if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
  1325. int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
  1326. MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
  1327. mHandler.removeMessages(msg);
  1328. mHandler.sendEmptyMessage(msg);
  1329. }
  1330.  
  1331. public void onClickCompatModeButton() {
  1332. int msg = (mCompatModePanel.getVisibility() == View.GONE) ?
  1333. MSG_OPEN_COMPAT_MODE_PANEL : MSG_CLOSE_COMPAT_MODE_PANEL;
  1334. mHandler.removeMessages(msg);
  1335. mHandler.sendEmptyMessage(msg);
  1336. }
  1337.  
  1338. private class NotificationTriggerTouchListener implements View.OnTouchListener {
  1339. VelocityTracker mVT;
  1340. float mInitialTouchX, mInitialTouchY;
  1341. int mTouchSlop;
  1342.  
  1343. public NotificationTriggerTouchListener() {
  1344. mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
  1345. }
  1346.  
  1347. private Runnable mHiliteOnR = new Runnable() { public void run() {
  1348. mNotificationArea.setBackgroundResource(
  1349. com.android.internal.R.drawable.list_selector_pressed_holo_dark);
  1350. }};
  1351. public void hilite(final boolean on) {
  1352. if (on) {
  1353. mNotificationArea.postDelayed(mHiliteOnR, 100);
  1354. } else {
  1355. mNotificationArea.removeCallbacks(mHiliteOnR);
  1356. mNotificationArea.setBackground(null);
  1357. }
  1358. }
  1359.  
  1360. public boolean onTouch(View v, MotionEvent event) {
  1361. // Slog.d(TAG, String.format("touch: (%.1f, %.1f) initial: (%.1f, %.1f)",
  1362. // event.getX(),
  1363. // event.getY(),
  1364. // mInitialTouchX,
  1365. // mInitialTouchY));
  1366.  
  1367. if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
  1368. return true;
  1369. }
  1370.  
  1371. final int action = event.getAction();
  1372. switch (action) {
  1373. case MotionEvent.ACTION_DOWN:
  1374. mVT = VelocityTracker.obtain();
  1375. mInitialTouchX = event.getX();
  1376. mInitialTouchY = event.getY();
  1377. hilite(true);
  1378. // fall through
  1379. case MotionEvent.ACTION_OUTSIDE:
  1380. case MotionEvent.ACTION_MOVE:
  1381. // check for fling
  1382. if (mVT != null) {
  1383. mVT.addMovement(event);
  1384. mVT.computeCurrentVelocity(1000); // pixels per second
  1385. // require a little more oomph once we're already in peekaboo mode
  1386. if (mVT.getYVelocity() < -mNotificationFlingVelocity) {
  1387. animateExpandNotificationsPanel();
  1388. visibilityChanged(true);
  1389. hilite(false);
  1390. mVT.recycle();
  1391. mVT = null;
  1392. }
  1393. }
  1394. return true;
  1395. case MotionEvent.ACTION_UP:
  1396. case MotionEvent.ACTION_CANCEL:
  1397. hilite(false);
  1398. if (mVT != null) {
  1399. if (action == MotionEvent.ACTION_UP
  1400. // was this a sloppy tap?
  1401. && Math.abs(event.getX() - mInitialTouchX) < mTouchSlop
  1402. && Math.abs(event.getY() - mInitialTouchY) < (mTouchSlop / 3)
  1403. // dragging off the bottom doesn't count
  1404. && (int)event.getY() < v.getBottom()) {
  1405. animateExpandNotificationsPanel();
  1406. visibilityChanged(true);
  1407. v.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
  1408. v.playSoundEffect(SoundEffectConstants.CLICK);
  1409. }
  1410.  
  1411. mVT.recycle();
  1412. mVT = null;
  1413. return true;
  1414. }
  1415. }
  1416. return false;
  1417. }
  1418. }
  1419.  
  1420. public void resetNotificationPeekFadeTimer() {
  1421. if (DEBUG) {
  1422. Slog.d(TAG, "setting peek fade timer for " + NOTIFICATION_PEEK_FADE_DELAY
  1423. + "ms from now");
  1424. }
  1425. mHandler.removeMessages(MSG_CLOSE_NOTIFICATION_PEEK);
  1426. mHandler.sendEmptyMessageDelayed(MSG_CLOSE_NOTIFICATION_PEEK,
  1427. NOTIFICATION_PEEK_FADE_DELAY);
  1428. }
  1429.  
  1430. private void reloadAllNotificationIcons() {
  1431. if (mIconLayout == null) return;
  1432. mIconLayout.removeAllViews();
  1433. updateNotificationIcons();
  1434. }
  1435.  
  1436. @Override
  1437. protected void updateNotificationIcons() {
  1438. // XXX: need to implement a new limited linear layout class
  1439. // to avoid removing & readding everything
  1440.  
  1441. if (mIconLayout == null) return;
  1442.  
  1443. // first, populate the main notification panel
  1444. loadNotificationPanel();
  1445.  
  1446. final LinearLayout.LayoutParams params
  1447. = new LinearLayout.LayoutParams(mIconSize + 2*mIconHPadding, mNaturalBarHeight);
  1448.  
  1449. // alternate behavior in DND mode
  1450. if (mNotificationDNDMode) {
  1451. if (mIconLayout.getChildCount() == 0) {
  1452. final Notification dndNotification = new Notification.Builder(mContext)
  1453. .setContentTitle(mContext.getText(R.string.notifications_off_title))
  1454. .setContentText(mContext.getText(R.string.notifications_off_text))
  1455. .setSmallIcon(R.drawable.ic_notification_dnd)
  1456. .setOngoing(true)
  1457. .getNotification();
  1458.  
  1459. final StatusBarIconView iconView = new StatusBarIconView(mContext, "_dnd",
  1460. dndNotification);
  1461. iconView.setImageResource(R.drawable.ic_notification_dnd);
  1462. iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
  1463. iconView.setPadding(mIconHPadding, 0, mIconHPadding, 0);
  1464.  
  1465. mNotificationDNDDummyEntry = new NotificationData.Entry(
  1466. null, new StatusBarNotification("", 0, "", 0, 0, Notification.PRIORITY_MAX,
  1467. dndNotification, android.os.Process.myUserHandle()), iconView);
  1468.  
  1469. mIconLayout.addView(iconView, params);
  1470. }
  1471.  
  1472. return;
  1473. } else if (0 != (mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) {
  1474. // if icons are disabled but we're not in DND mode, this is probably Setup and we should
  1475. // just leave the area totally empty
  1476. return;
  1477. }
  1478.  
  1479. int N = mNotificationData.size();
  1480.  
  1481. if (DEBUG) {
  1482. Slog.d(TAG, "refreshing icons: " + N + " notifications, mIconLayout=" + mIconLayout);
  1483. }
  1484.  
  1485. ArrayList<View> toShow = new ArrayList<View>();
  1486.  
  1487. // Extra Special Icons
  1488. // The IME switcher and compatibility mode icons take the place of notifications. You didn't
  1489. // need to see all those new emails, did you?
  1490. int maxNotificationIconsCount = mMaxNotificationIcons;
  1491. if (mInputMethodSwitchButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
  1492. if (mCompatModeButton.getVisibility() != View.GONE) maxNotificationIconsCount --;
  1493.  
  1494. final boolean provisioned = isDeviceProvisioned();
  1495. // If the device hasn't been through Setup, we only show system notifications
  1496. for (int i=0; toShow.size()< maxNotificationIconsCount; i++) {
  1497. if (i >= N) break;
  1498. Entry ent = mNotificationData.get(N-i-1);
  1499. if ((provisioned && ent.notification.score >= HIDE_ICONS_BELOW_SCORE)
  1500. || showNotificationEvenIfUnprovisioned(ent.notification)) {
  1501. toShow.add(ent.icon);
  1502. }
  1503. }
  1504.  
  1505. ArrayList<View> toRemove = new ArrayList<View>();
  1506. for (int i=0; i<mIconLayout.getChildCount(); i++) {
  1507. View child = mIconLayout.getChildAt(i);
  1508. if (!toShow.contains(child)) {
  1509. toRemove.add(child);
  1510. }
  1511. }
  1512.  
  1513. for (View remove : toRemove) {
  1514. mIconLayout.removeView(remove);
  1515. }
  1516.  
  1517. for (int i=0; i<toShow.size(); i++) {
  1518. View v = toShow.get(i);
  1519. v.setPadding(mIconHPadding, 0, mIconHPadding, 0);
  1520. if (v.getParent() == null) {
  1521. mIconLayout.addView(v, i, params);
  1522. }
  1523. }
  1524. }
  1525.  
  1526. private void loadNotificationPanel() {
  1527. int N = mNotificationData.size();
  1528.  
  1529. ArrayList<View> toShow = new ArrayList<View>();
  1530.  
  1531. final boolean provisioned = isDeviceProvisioned();
  1532. // If the device hasn't been through Setup, we only show system notifications
  1533. for (int i=0; i<N; i++) {
  1534. Entry ent = mNotificationData.get(N-i-1);
  1535. if (provisioned || showNotificationEvenIfUnprovisioned(ent.notification)) {
  1536. toShow.add(ent.row);
  1537. }
  1538. }
  1539.  
  1540. ArrayList<View> toRemove = new ArrayList<View>();
  1541. for (int i=0; i<mPile.getChildCount(); i++) {
  1542. View child = mPile.getChildAt(i);
  1543. if (!toShow.contains(child)) {
  1544. toRemove.add(child);
  1545. }
  1546. }
  1547.  
  1548. for (View remove : toRemove) {
  1549. mPile.removeView(remove);
  1550. }
  1551.  
  1552. for (int i=0; i<toShow.size(); i++) {
  1553. View v = toShow.get(i);
  1554. if (v.getParent() == null) {
  1555. // the notification panel has the most important things at the bottom
  1556. mPile.addView(v, Math.min(toShow.size()-1-i, mPile.getChildCount()));
  1557. }
  1558. }
  1559.  
  1560. mNotificationPanel.setNotificationCount(toShow.size());
  1561. mNotificationPanel.setSettingsEnabled(isDeviceProvisioned());
  1562. }
  1563.  
  1564. @Override
  1565. protected void workAroundBadLayerDrawableOpacity(View v) {
  1566. Drawable bgd = v.getBackground();
  1567. if (!(bgd instanceof LayerDrawable)) return;
  1568.  
  1569. LayerDrawable d = (LayerDrawable) bgd;
  1570. v.setBackground(null);
  1571. d.setOpacity(PixelFormat.TRANSLUCENT);
  1572. v.setBackground(d);
  1573. }
  1574.  
  1575. public void clearAll() {
  1576. try {
  1577. mBarService.onClearAllNotifications();
  1578. } catch (RemoteException ex) {
  1579. // system process is dead if we're here.
  1580. }
  1581. animateCollapsePanels();
  1582. visibilityChanged(false);
  1583. }
  1584.  
  1585. private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
  1586. public void onReceive(Context context, Intent intent) {
  1587. String action = intent.getAction();
  1588. if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)
  1589. || Intent.ACTION_SCREEN_OFF.equals(action)) {
  1590. int flags = CommandQueue.FLAG_EXCLUDE_NONE;
  1591. if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
  1592. String reason = intent.getStringExtra("reason");
  1593. if (reason != null && reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
  1594. flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
  1595. }
  1596. }
  1597. animateCollapsePanels(flags);
  1598. }
  1599. }
  1600. };
  1601.  
  1602. public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  1603. pw.print("mDisabled=0x");
  1604. pw.println(Integer.toHexString(mDisabled));
  1605. pw.println("mNetworkController:");
  1606. mNetworkController.dump(fd, pw, args);
  1607. }
  1608.  
  1609. @Override
  1610. protected boolean isTopNotification(ViewGroup parent, NotificationData.Entry entry) {
  1611. if (parent == null || entry == null) return false;
  1612. return parent.indexOfChild(entry.row) == parent.getChildCount()-1;
  1613. }
  1614.  
  1615. @Override
  1616. protected void haltTicker() {
  1617. mTicker.halt();
  1618. }
  1619.  
  1620. @Override
  1621. protected void updateExpandedViewPos(int expandedPosition) {
  1622. }
  1623.  
  1624. @Override
  1625. protected boolean shouldDisableNavbarGestures() {
  1626. return mNotificationPanel.getVisibility() == View.VISIBLE
  1627. || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
  1628. }
  1629. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement