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