1ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato/* 2ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * Copyright (C) 2010 The Android Open Source Project 3ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * 4ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * Licensed under the Apache License, Version 2.0 (the "License"); 5ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * you may not use this file except in compliance with the License. 6ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * You may obtain a copy of the License at 7ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * 8ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * http://www.apache.org/licenses/LICENSE-2.0 9ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * 10ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * Unless required by applicable law or agreed to in writing, software 11ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * distributed under the License is distributed on an "AS IS" BASIS, 12ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * See the License for the specific language governing permissions and 14ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato * limitations under the License. 15ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato */ 16ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 17ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratopackage com.android.systemui.statusbar.tablet; 18ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 192026e8d4681437fb056409bc95bc2f126582e4a8Joe Onoratoimport java.util.Arrays; 202026e8d4681437fb056409bc95bc2f126582e4a8Joe Onorato 21c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandlerimport android.animation.LayoutTransition; 22ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.app.Notification; 23c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandlerimport android.app.PendingIntent; 24ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.content.Context; 2552f80cd36f406725e85a1825741a45c69de3d898Joe Onoratoimport android.content.res.Resources; 26ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.graphics.Bitmap; 2752f80cd36f406725e85a1825741a45c69de3d898Joe Onoratoimport android.graphics.PixelFormat; 282026e8d4681437fb056409bc95bc2f126582e4a8Joe Onoratoimport android.graphics.drawable.Drawable; 29ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.os.Handler; 3050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onoratoimport android.os.IBinder; 31ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.os.Message; 32ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.util.Slog; 33ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.view.Gravity; 34ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.view.LayoutInflater; 35ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.view.View; 36ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.view.ViewGroup; 3752f80cd36f406725e85a1825741a45c69de3d898Joe Onoratoimport android.view.WindowManager; 3852f80cd36f406725e85a1825741a45c69de3d898Joe Onoratoimport android.view.WindowManagerImpl; 39ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.widget.FrameLayout; 40ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.widget.ImageView; 416aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandlerimport android.widget.FrameLayout; 42ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport android.widget.TextView; 43ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 442026e8d4681437fb056409bc95bc2f126582e4a8Joe Onoratoimport com.android.internal.statusbar.StatusBarIcon; 45ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport com.android.internal.statusbar.StatusBarNotification; 46ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 47ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onoratoimport com.android.systemui.R; 482026e8d4681437fb056409bc95bc2f126582e4a8Joe Onoratoimport com.android.systemui.statusbar.StatusBarIconView; 49ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 50c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandlerpublic class TabletTicker 51c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler extends Handler 52c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler implements LayoutTransition.TransitionListener { 53c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 54ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private static final String TAG = "StatusBar.TabletTicker"; 55ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 56e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler private static final boolean CLICKABLE_TICKER = true; 57c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 5850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato // 3 is enough to let us see most cases, but not get so far behind that it's too annoying. 5950ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato private static final int QUEUE_LENGTH = 3; 6050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato 61ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private static final int MSG_ADVANCE = 1; 62ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 636c1af93c17cf1ebf17ecbee12cbed27db5a26a0bJoe Onorato private static final int ADVANCE_DELAY = 5000; // 5 seconds 64ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 65ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private Context mContext; 66ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 6752f80cd36f406725e85a1825741a45c69de3d898Joe Onorato private ViewGroup mWindow; 6850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato private IBinder mCurrentKey; 69ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private StatusBarNotification mCurrentNotification; 70ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private View mCurrentView; 71ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 7250ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato private IBinder[] mKeys = new IBinder[QUEUE_LENGTH]; 7350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato private StatusBarNotification[] mQueue = new StatusBarNotification[QUEUE_LENGTH]; 74ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private int mQueuePos; 75ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 76a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler private final int mLargeIconHeight; 77a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler 78c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler private TabletStatusBar mBar; 79c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 80c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler private LayoutTransition mLayoutTransition; 81c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler private boolean mWindowShouldClose; 82c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 83c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler public TabletTicker(TabletStatusBar bar) { 84c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mBar = bar; 85c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mContext = bar.getContext(); 86a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler final Resources res = mContext.getResources(); 87a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler mLargeIconHeight = res.getDimensionPixelSize( 88a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler android.R.dimen.notification_large_icon_height); 89ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 90ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 9150ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato public void add(IBinder key, StatusBarNotification notification) { 92ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato if (false) { 9350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato Slog.d(TAG, "add 1 mCurrentNotification=" + mCurrentNotification 94ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato + " mQueuePos=" + mQueuePos + " mQueue=" + Arrays.toString(mQueue)); 95ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 9650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato 9750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato // If it's already in here, remove whatever's in there and put the new one at the end. 9850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato remove(key, false); 9950ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato 10050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[mQueuePos] = key; 101ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mQueue[mQueuePos] = notification; 102ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 10350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato // If nothing is running now, start the next one. 10450ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (mQueuePos == 0 && mCurrentNotification == null) { 105ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato sendEmptyMessage(MSG_ADVANCE); 106ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 107ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 10850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (mQueuePos < QUEUE_LENGTH - 1) { 109ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mQueuePos++; 110ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 111ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 112ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 11350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato public void remove(IBinder key) { 11450ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato remove(key, true); 11550ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 11650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato 11750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato public void remove(IBinder key, boolean advance) { 11850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (mCurrentKey == key) { 11950ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato // Showing now 12050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (advance) { 12150ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato removeMessages(MSG_ADVANCE); 12250ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato sendEmptyMessage(MSG_ADVANCE); 12350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 12450ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } else { 12550ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato // In the queue 12650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato for (int i=0; i<QUEUE_LENGTH; i++) { 12750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (mKeys[i] == key) { 12850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato for (; i<QUEUE_LENGTH-1; i++) { 12950ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[i] = mKeys[i+1]; 13050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mQueue[i] = mQueue[i+1]; 13150ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 13250ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[QUEUE_LENGTH-1] = null; 13350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mQueue[QUEUE_LENGTH-1] = null; 13450ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato if (mQueuePos > 0) { 13550ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mQueuePos--; 13650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 13750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato break; 13850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 13950ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 14050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 14150ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato } 14250ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato 143091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato public void halt() { 144091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato removeMessages(MSG_ADVANCE); 145af5e4da2a5766198f533f1ff9e2072d2cd5c63d4Joe Onorato if (mCurrentView != null || mQueuePos != 0) { 14650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato for (int i=0; i<QUEUE_LENGTH; i++) { 14750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[i] = null; 148091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato mQueue[i] = null; 149091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato } 150091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato mQueuePos = 0; 151091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato sendEmptyMessage(MSG_ADVANCE); 152091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato } 153091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato } 154091e1b8a86d34d2d51d2a5f7ae3cd903925fa5bfJoe Onorato 155ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato public void handleMessage(Message msg) { 156ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato switch (msg.what) { 157ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato case MSG_ADVANCE: 158ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato advance(); 159ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato break; 160ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 161ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 162ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 163ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private void advance() { 164ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato // Out with the old... 165ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato if (mCurrentView != null) { 166bec7d63c9cad875bb127786d61ee34b4d609db59Daniel Sandler if (mWindow != null) { 167bec7d63c9cad875bb127786d61ee34b4d609db59Daniel Sandler mWindow.removeView(mCurrentView); 168bec7d63c9cad875bb127786d61ee34b4d609db59Daniel Sandler } 169ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mCurrentView = null; 17050ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mCurrentKey = null; 171ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mCurrentNotification = null; 172ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 173ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 174ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato // In with the new... 17550ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato dequeue(); 17650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato while (mCurrentNotification != null) { 17750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mCurrentView = makeTickerView(mCurrentNotification); 17846439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato if (mCurrentView != null) { 17952f80cd36f406725e85a1825741a45c69de3d898Joe Onorato if (mWindow == null) { 18052f80cd36f406725e85a1825741a45c69de3d898Joe Onorato mWindow = makeWindow(); 18152f80cd36f406725e85a1825741a45c69de3d898Joe Onorato WindowManagerImpl.getDefault().addView(mWindow, mWindow.getLayoutParams()); 18252f80cd36f406725e85a1825741a45c69de3d898Joe Onorato } 1836aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler 18452f80cd36f406725e85a1825741a45c69de3d898Joe Onorato mWindow.addView(mCurrentView); 18546439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato sendEmptyMessageDelayed(MSG_ADVANCE, ADVANCE_DELAY); 18646439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato break; 18746439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato } 18850ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato dequeue(); 189ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 19052f80cd36f406725e85a1825741a45c69de3d898Joe Onorato 19152f80cd36f406725e85a1825741a45c69de3d898Joe Onorato // if there's nothing left, close the window 192c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mWindowShouldClose = (mCurrentView == null && mWindow != null); 193ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 194ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 19550ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato private void dequeue() { 19650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mCurrentKey = mKeys[0]; 19750ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mCurrentNotification = mQueue[0]; 198ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato if (false) { 199ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato Slog.d(TAG, "dequeue mQueuePos=" + mQueuePos + " mQueue=" + Arrays.toString(mQueue)); 200ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 201ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato final int N = mQueuePos; 202ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato for (int i=0; i<N; i++) { 20350ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[i] = mKeys[i+1]; 204ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mQueue[i] = mQueue[i+1]; 205ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 20650ec5ec0b8b3ab9cf697c8e3925e3fdd837f5e7dJoe Onorato mKeys[N] = null; 207ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mQueue[N] = null; 208ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato if (mQueuePos > 0) { 209ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato mQueuePos--; 210ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 211ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 212ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 21352f80cd36f406725e85a1825741a45c69de3d898Joe Onorato private ViewGroup makeWindow() { 21452f80cd36f406725e85a1825741a45c69de3d898Joe Onorato final Resources res = mContext.getResources(); 21552f80cd36f406725e85a1825741a45c69de3d898Joe Onorato final FrameLayout view = new FrameLayout(mContext); 21652f80cd36f406725e85a1825741a45c69de3d898Joe Onorato final int width = res.getDimensionPixelSize(R.dimen.notification_ticker_width); 217ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato int windowFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 2186c1af93c17cf1ebf17ecbee12cbed27db5a26a0bJoe Onorato | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 219ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 220ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato if (CLICKABLE_TICKER) { 221ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; 222ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato } else { 223ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 224ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato } 225a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, mLargeIconHeight, 226ec51a82bd6e7a33fe6ed84ba252b82625629eaacJoe Onorato WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL, windowFlags, 22752f80cd36f406725e85a1825741a45c69de3d898Joe Onorato PixelFormat.TRANSLUCENT); 22852f80cd36f406725e85a1825741a45c69de3d898Joe Onorato lp.gravity = Gravity.BOTTOM | Gravity.RIGHT; 229c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler// lp.windowAnimations = com.android.internal.R.style.Animation_Toast; 230c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 231c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mLayoutTransition = new LayoutTransition(); 232c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mLayoutTransition.addTransitionListener(this); 233c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler view.setLayoutTransition(mLayoutTransition); 23452f80cd36f406725e85a1825741a45c69de3d898Joe Onorato lp.setTitle("NotificationTicker"); 23552f80cd36f406725e85a1825741a45c69de3d898Joe Onorato view.setLayoutParams(lp); 23652f80cd36f406725e85a1825741a45c69de3d898Joe Onorato return view; 23752f80cd36f406725e85a1825741a45c69de3d898Joe Onorato } 23852f80cd36f406725e85a1825741a45c69de3d898Joe Onorato 239c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler public void startTransition(LayoutTransition transition, ViewGroup container, 240c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler View view, int transitionType) {} 241c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 242c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler public void endTransition(LayoutTransition transition, ViewGroup container, 243c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler View view, int transitionType) { 244c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler if (mWindowShouldClose) { 245c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler WindowManagerImpl.getDefault().removeView(mWindow); 246c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mWindow = null; 247c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler mWindowShouldClose = false; 248b8027d87d87fbf24a6091ef183e519157876df41Daniel Sandler mBar.doneTicking(); 249c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler } 250c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler } 251c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 252ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato private View makeTickerView(StatusBarNotification notification) { 253ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato final Notification n = notification.notification; 254ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 255ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato LayoutInflater inflater = (LayoutInflater)mContext.getSystemService( 256ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato Context.LAYOUT_INFLATER_SERVICE); 257ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 258ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato ViewGroup group; 25946439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato int layoutId; 260561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato int iconId; 261561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato if (n.largeIcon != null) { 262561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato iconId = R.id.right_icon; 263561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato } else { 264561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato iconId = R.id.left_icon; 265561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato } 26646439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato if (n.tickerView != null) { 267755cc74e4cebdf67d21a2477512a4ac9b01e8323Joe Onorato group = (ViewGroup)inflater.inflate(R.layout.status_bar_ticker_panel, null, false); 2686aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler ViewGroup content = (FrameLayout) group.findViewById(R.id.ticker_expanded); 26946439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato View expanded = null; 27046439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato Exception exception = null; 27146439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato try { 2726aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler expanded = n.tickerView.apply(mContext, content); 273ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 27446439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato catch (RuntimeException e) { 27546439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato exception = e; 276ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 27746439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato if (expanded == null) { 27846439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato final String ident = notification.pkg 27946439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato + "/0x" + Integer.toHexString(notification.id); 28046439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato Slog.e(TAG, "couldn't inflate view for notification " + ident, exception); 28146439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato return null; 28246439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato } 2836aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( 2846aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler ViewGroup.LayoutParams.MATCH_PARENT, 2856aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler ViewGroup.LayoutParams.MATCH_PARENT); 2866aa2d3a166b7b2fe5362931297953d08c17a0fb6Daniel Sandler content.addView(expanded, lp); 28746439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato } else if (n.tickerText != null) { 288755cc74e4cebdf67d21a2477512a4ac9b01e8323Joe Onorato group = (ViewGroup)inflater.inflate(R.layout.status_bar_ticker_compat, mWindow, false); 2892026e8d4681437fb056409bc95bc2f126582e4a8Joe Onorato final Drawable icon = StatusBarIconView.getIcon(mContext, 2906179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov new StatusBarIcon(notification.pkg, n.icon, n.iconLevel, 0, n.tickerText)); 291561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato ImageView iv = (ImageView)group.findViewById(iconId); 2922026e8d4681437fb056409bc95bc2f126582e4a8Joe Onorato iv.setImageDrawable(icon); 293561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato iv.setVisibility(View.VISIBLE); 294ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato TextView tv = (TextView)group.findViewById(R.id.text); 295ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato tv.setText(n.tickerText); 29646439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato } else { 29746439cec0eb0da4d0f853f2d8712d0c00c98475bJoe Onorato throw new RuntimeException("tickerView==null && tickerText==null"); 298ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 299561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato ImageView largeIcon = (ImageView)group.findViewById(R.id.large_icon); 300561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato if (n.largeIcon != null) { 301561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato largeIcon.setImageBitmap(n.largeIcon); 302561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato largeIcon.setVisibility(View.VISIBLE); 303a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler final ViewGroup.LayoutParams lp = largeIcon.getLayoutParams(); 304a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler final int statusBarHeight = mBar.getStatusBarHeight(); 305a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler if (n.largeIcon.getHeight() <= statusBarHeight) { 306a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler // for smallish largeIcons, it looks a little odd to have them floating halfway up 307a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler // the ticker, so we vertically center them in the status bar area instead 308a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler lp.height = statusBarHeight; 309a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler } else { 310a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler lp.height = mLargeIconHeight; 311a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler } 312a3850b68399ab49032e1fc2a2eab129fe3a7e69eDaniel Sandler largeIcon.setLayoutParams(lp); 313561d3858bb9409b999a19f7ba93f0b12e1db835fJoe Onorato } 314c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 315c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler if (CLICKABLE_TICKER) { 316c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler PendingIntent contentIntent = notification.notification.contentIntent; 317c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler if (contentIntent != null) { 318e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler // create the usual notification clicker, but chain it together with a halt() call 319e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler // to abort the ticker too 320e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler final View.OnClickListener clicker = mBar.makeClicker(contentIntent, 321e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler notification.pkg, notification.tag, notification.id); 322e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler group.setOnClickListener(new View.OnClickListener() { 323e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler public void onClick(View v) { 324e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler halt(); 325e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler clicker.onClick(v); 326e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler } 327e2c251b564a46a8f7352094ba8a61d46dc6b676fDaniel Sandler }); 328c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler } else { 329c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler group.setOnClickListener(null); 330c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler } 331c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler } 332c51451a318af8e7076e7789bc1fcd91454f1e5a9Daniel Sandler 333ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato return group; 334ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato } 335ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato} 336ef1e7763c2dc5b9bac69cc747efe05c81d9fd9fcJoe Onorato 337