109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/*
209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * All rights reserved.
509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Redistribution and use in source and binary forms, with or without
709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * modification, are permitted provided that the following conditions are met:
809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions of source code must retain the above copyright notice,
1009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer.
1109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
1209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
1309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer in the documentation
1409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * and/or other materials provided with the distribution.
1509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
1609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
1709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * may be used to endorse or promote products derived from this software
1809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * without specific prior written permission.
1909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
2009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
3109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */
3209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypackage com.android.bluetooth.opp;
3409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
356769b59d715ea98bd72eafcfea9acd2714a887daTao Liejunimport com.android.bluetooth.R;
366769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun
3709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context;
3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.app.Notification;
3909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.app.NotificationManager;
4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.app.PendingIntent;
4109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent;
4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.Cursor;
4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri;
4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log;
4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.widget.RemoteViews;
46eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Taoimport android.os.Handler;
47eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Taoimport android.os.Message;
481ac5507790a87810061a19dadec36eb328a222eaTao Liejunimport android.os.Process;
4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.util.HashMap;
5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/**
5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This class handles the updating of the Notification Manager for the cases
5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * where there is an ongoing transfer, incoming transfer need confirm and
5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * complete (successful or failed) transfer.
5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */
5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyclass BluetoothOppNotification {
5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static final String TAG = "BluetoothOppNotification";
58ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final boolean V = Constants.VERBOSE;
5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String status = "(" + BluetoothShare.STATUS + " == '192'" + ")";
6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String visible = "(" + BluetoothShare.VISIBILITY + " IS NULL OR "
6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            + BluetoothShare.VISIBILITY + " == '" + BluetoothShare.VISIBILITY_VISIBLE + "'" + ")";
6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String confirm = "(" + BluetoothShare.USER_CONFIRMATION + " == '"
6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            + BluetoothShare.USER_CONFIRMATION_CONFIRMED + "' OR "
6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            + BluetoothShare.USER_CONFIRMATION + " == '"
6809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            + BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED + "'" + ")";
6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String WHERE_RUNNING = status + " AND " + visible + " AND " + confirm;
7109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String WHERE_COMPLETED = BluetoothShare.STATUS + " >= '200' AND " + visible;
7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
745cc617943765df27844e459362c4bc1821305216Lixin Yue    private static final String WHERE_COMPLETED_OUTBOUND = WHERE_COMPLETED + " AND " + "("
755cc617943765df27844e459362c4bc1821305216Lixin Yue            + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_OUTBOUND + ")";
765cc617943765df27844e459362c4bc1821305216Lixin Yue
775cc617943765df27844e459362c4bc1821305216Lixin Yue    private static final String WHERE_COMPLETED_INBOUND = WHERE_COMPLETED + " AND " + "("
785cc617943765df27844e459362c4bc1821305216Lixin Yue            + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_INBOUND + ")";
795cc617943765df27844e459362c4bc1821305216Lixin Yue
8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static final String WHERE_CONFIRM_PENDING = BluetoothShare.USER_CONFIRMATION + " == '"
8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            + BluetoothShare.USER_CONFIRMATION_PENDING + "'" + " AND " + visible;
8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
831ac5507790a87810061a19dadec36eb328a222eaTao Liejun    public NotificationManager mNotificationMgr;
841ac5507790a87810061a19dadec36eb328a222eaTao Liejun
851ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private Context mContext;
861ac5507790a87810061a19dadec36eb328a222eaTao Liejun
871ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private HashMap<String, NotificationItem> mNotifications;
881ac5507790a87810061a19dadec36eb328a222eaTao Liejun
891ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private NotificationUpdateThread mUpdateNotificationThread;
901ac5507790a87810061a19dadec36eb328a222eaTao Liejun
91eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    private int mPendingUpdate = 0;
921ac5507790a87810061a19dadec36eb328a222eaTao Liejun
935cc617943765df27844e459362c4bc1821305216Lixin Yue    private static final int NOTIFICATION_ID_OUTBOUND = -1000005;
945cc617943765df27844e459362c4bc1821305216Lixin Yue
955cc617943765df27844e459362c4bc1821305216Lixin Yue    private static final int NOTIFICATION_ID_INBOUND = -1000006;
965cc617943765df27844e459362c4bc1821305216Lixin Yue
975cc617943765df27844e459362c4bc1821305216Lixin Yue    private boolean mUpdateCompleteNotification = true;
985cc617943765df27844e459362c4bc1821305216Lixin Yue
995cc617943765df27844e459362c4bc1821305216Lixin Yue    private int mActiveNotificationId = 0;
1005cc617943765df27844e459362c4bc1821305216Lixin Yue
10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * This inner class is used to describe some properties for one transfer.
10309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    static class NotificationItem {
10509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int id; // This first field _id in db;
10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int direction; // to indicate sending or receiving
10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int totalCurrent = 0; // current transfer bytes
11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int totalTotal = 0; // total bytes for current transfer
11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
11374e5eba4a45ecca87eec3ac1762ca527cc614d78erik.ljungberg        int timeStamp = 0; // Database time stamp. Used for sorting ongoing transfers.
11474e5eba4a45ecca87eec3ac1762ca527cc614d78erik.ljungberg
11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        String description; // the text above progress bar
11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Constructor
120239bc526513429995c61c4148c105725c395b1a9Jackson Fan     *
121239bc526513429995c61c4148c105725c395b1a9Jackson Fan     * @param ctx The context to use to obtain access to the Notification
122239bc526513429995c61c4148c105725c395b1a9Jackson Fan     *            Service
12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    BluetoothOppNotification(Context ctx) {
12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mContext = ctx;
12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotificationMgr = (NotificationManager)mContext
12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                .getSystemService(Context.NOTIFICATION_SERVICE);
12809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotifications = new HashMap<String, NotificationItem>();
12909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
13009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
13209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Update the notification ui.
13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void updateNotification() {
135c6f1bacf1d4c39d7efd5dc98004d936c18ed51f1Lixin Yue        synchronized (BluetoothOppNotification.this) {
136eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            mPendingUpdate++;
137eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            if (mPendingUpdate > 1) {
138eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                if (V) Log.v(TAG, "update too frequent, put in queue");
139eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                return;
140eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            }
141eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            if (!mHandler.hasMessages(NOTIFY)) {
142eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                if (V) Log.v(TAG, "send message");
143eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                mHandler.sendMessage(mHandler.obtainMessage(NOTIFY));
1441ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
1451ac5507790a87810061a19dadec36eb328a222eaTao Liejun        }
1461ac5507790a87810061a19dadec36eb328a222eaTao Liejun    }
1471ac5507790a87810061a19dadec36eb328a222eaTao Liejun
148eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    private static final int NOTIFY = 0;
149eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // Use 1 second timer to limit notification frequency.
150eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // 1. On the first notification, create the update thread.
151eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    //    Buffer other updates.
152eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // 2. Update thread will clear mPendingUpdate.
153eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // 3. Handler sends a delayed message to self
154eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // 4. Handler checks if there are any more updates after 1 second.
155eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    // 5. If there is an update, update it else stop.
156eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    private Handler mHandler = new Handler() {
157eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao        public void handleMessage(Message msg) {
158eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            switch (msg.what) {
159eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                case NOTIFY:
160eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                    synchronized (BluetoothOppNotification.this) {
161eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                        if (mPendingUpdate > 0 && mUpdateNotificationThread == null) {
162eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            if (V) Log.v(TAG, "new notify threadi!");
163eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            mUpdateNotificationThread = new NotificationUpdateThread();
164eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            mUpdateNotificationThread.start();
165eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            if (V) Log.v(TAG, "send delay message");
166eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000);
167eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                        } else if (mPendingUpdate > 0) {
168eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            if (V) Log.v(TAG, "previous thread is not finished yet");
169eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000);
170eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                        }
171eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                        break;
172eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                    }
173eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao              }
174eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao         }
175eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao    };
176eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao
1771ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private class NotificationUpdateThread extends Thread {
1781ac5507790a87810061a19dadec36eb328a222eaTao Liejun
1791ac5507790a87810061a19dadec36eb328a222eaTao Liejun        public NotificationUpdateThread() {
1801ac5507790a87810061a19dadec36eb328a222eaTao Liejun            super("Notification Update Thread");
1811ac5507790a87810061a19dadec36eb328a222eaTao Liejun        }
1821ac5507790a87810061a19dadec36eb328a222eaTao Liejun
1831ac5507790a87810061a19dadec36eb328a222eaTao Liejun        @Override
1841ac5507790a87810061a19dadec36eb328a222eaTao Liejun        public void run() {
1851ac5507790a87810061a19dadec36eb328a222eaTao Liejun            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
186eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            synchronized (BluetoothOppNotification.this) {
187eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                if (mUpdateNotificationThread != this) {
188eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                    throw new IllegalStateException(
189eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                            "multiple UpdateThreads in BluetoothOppNotification");
1901ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
191eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                mPendingUpdate = 0;
192eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            }
193eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            updateActiveNotification();
194eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            updateCompletedNotification();
195eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            updateIncomingFileConfirmNotification();
196eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao            synchronized (BluetoothOppNotification.this) {
197eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao                mUpdateNotificationThread = null;
1981ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
1991ac5507790a87810061a19dadec36eb328a222eaTao Liejun        }
20009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
20109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void updateActiveNotification() {
20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        // Active transfers
20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null,
20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                WHERE_RUNNING, null, BluetoothShare._ID);
20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (cursor == null) {
20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return;
20809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
2105cc617943765df27844e459362c4bc1821305216Lixin Yue        // If there is active transfers, then no need to update completed transfer
2115cc617943765df27844e459362c4bc1821305216Lixin Yue        // notifications
2125cc617943765df27844e459362c4bc1821305216Lixin Yue        if (cursor.getCount() > 0) {
2135cc617943765df27844e459362c4bc1821305216Lixin Yue            mUpdateCompleteNotification = false;
2145cc617943765df27844e459362c4bc1821305216Lixin Yue        } else {
2155cc617943765df27844e459362c4bc1821305216Lixin Yue            mUpdateCompleteNotification = true;
2165cc617943765df27844e459362c4bc1821305216Lixin Yue        }
2175cc617943765df27844e459362c4bc1821305216Lixin Yue        if (V) Log.v(TAG, "mUpdateCompleteNotification = " + mUpdateCompleteNotification);
2185cc617943765df27844e459362c4bc1821305216Lixin Yue
21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        // Collate the notifications
2205cc617943765df27844e459362c4bc1821305216Lixin Yue        final int timestampIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP);
2215cc617943765df27844e459362c4bc1821305216Lixin Yue        final int directionIndex = cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION);
2225cc617943765df27844e459362c4bc1821305216Lixin Yue        final int idIndex = cursor.getColumnIndexOrThrow(BluetoothShare._ID);
2235cc617943765df27844e459362c4bc1821305216Lixin Yue        final int totalBytesIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES);
2245cc617943765df27844e459362c4bc1821305216Lixin Yue        final int currentBytesIndex = cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES);
2255cc617943765df27844e459362c4bc1821305216Lixin Yue        final int dataIndex = cursor.getColumnIndexOrThrow(BluetoothShare._DATA);
2265cc617943765df27844e459362c4bc1821305216Lixin Yue        final int filenameHintIndex = cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT);
2275cc617943765df27844e459362c4bc1821305216Lixin Yue
22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotifications.clear();
22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
2305cc617943765df27844e459362c4bc1821305216Lixin Yue            int timeStamp = cursor.getInt(timestampIndex);
2315cc617943765df27844e459362c4bc1821305216Lixin Yue            int dir = cursor.getInt(directionIndex);
2325cc617943765df27844e459362c4bc1821305216Lixin Yue            int id = cursor.getInt(idIndex);
2335cc617943765df27844e459362c4bc1821305216Lixin Yue            int total = cursor.getInt(totalBytesIndex);
2345cc617943765df27844e459362c4bc1821305216Lixin Yue            int current = cursor.getInt(currentBytesIndex);
23509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
2365cc617943765df27844e459362c4bc1821305216Lixin Yue            String fileName = cursor.getString(dataIndex);
23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (fileName == null) {
2385cc617943765df27844e459362c4bc1821305216Lixin Yue                fileName = cursor.getString(filenameHintIndex);
23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (fileName == null) {
24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                fileName = mContext.getString(R.string.unknown_file);
24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            String batchID = Long.toString(timeStamp);
24509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
24609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            // sending objects in one batch has same timeStamp
24709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mNotifications.containsKey(batchID)) {
24809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                // NOTE: currently no such case
24909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                // Batch sending case
25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
25109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                NotificationItem item = new NotificationItem();
25274e5eba4a45ecca87eec3ac1762ca527cc614d78erik.ljungberg                item.timeStamp = timeStamp;
25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                item.id = id;
25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                item.direction = dir;
25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (item.direction == BluetoothShare.DIRECTION_OUTBOUND) {
256239bc526513429995c61c4148c105725c395b1a9Jackson Fan                    item.description = mContext.getString(R.string.notification_sending, fileName);
25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else if (item.direction == BluetoothShare.DIRECTION_INBOUND) {
258239bc526513429995c61c4148c105725c395b1a9Jackson Fan                    item.description = mContext
259239bc526513429995c61c4148c105725c395b1a9Jackson Fan                            .getString(R.string.notification_receiving, fileName);
26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
261ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "mDirection ERROR!");
26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                item.totalCurrent = current;
26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                item.totalTotal = total;
26509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mNotifications.put(batchID, item);
26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
268ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "ID=" + item.id + "; batchID=" + batchID + "; totoalCurrent"
26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            + item.totalCurrent + "; totalTotal=" + item.totalTotal);
27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
27209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        cursor.close();
27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        // Add the notifications
27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        for (NotificationItem item : mNotifications.values()) {
27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            // Build the notification object
277dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            // TODO: split description into two rows with filename in second row
278dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            Notification.Builder b = new Notification.Builder(mContext);
279dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setContentTitle(item.description);
280dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setContentInfo(
281dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby                    BluetoothOppUtility.formatProgressText(item.totalTotal, item.totalCurrent));
282dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setProgress(item.totalTotal, item.totalCurrent, item.totalTotal == -1);
283dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setWhen(item.timeStamp);
28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (item.direction == BluetoothShare.DIRECTION_OUTBOUND) {
285dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby                b.setSmallIcon(android.R.drawable.stat_sys_upload);
28609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else if (item.direction == BluetoothShare.DIRECTION_INBOUND) {
287dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby                b.setSmallIcon(android.R.drawable.stat_sys_download);
28809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
289ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "mDirection ERROR!");
29009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
291dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setOngoing(true);
29209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
29309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Intent intent = new Intent(Constants.ACTION_LIST);
29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
29509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setData(Uri.parse(BluetoothShare.CONTENT_URI + "/" + item.id));
29609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
297dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            b.setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent, 0));
298dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby            mNotificationMgr.notify(item.id, b.getNotification());
2995cc617943765df27844e459362c4bc1821305216Lixin Yue
3005cc617943765df27844e459362c4bc1821305216Lixin Yue            mActiveNotificationId = item.id;
30109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
30309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
30409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void updateCompletedNotification() {
3055cc617943765df27844e459362c4bc1821305216Lixin Yue        String title;
3065cc617943765df27844e459362c4bc1821305216Lixin Yue        String caption;
3075cc617943765df27844e459362c4bc1821305216Lixin Yue        long timeStamp = 0;
3085cc617943765df27844e459362c4bc1821305216Lixin Yue        int outboundSuccNumber = 0;
3095cc617943765df27844e459362c4bc1821305216Lixin Yue        int outboundFailNumber = 0;
3105cc617943765df27844e459362c4bc1821305216Lixin Yue        int outboundNum;
3115cc617943765df27844e459362c4bc1821305216Lixin Yue        int inboundNum;
3125cc617943765df27844e459362c4bc1821305216Lixin Yue        int inboundSuccNumber = 0;
3135cc617943765df27844e459362c4bc1821305216Lixin Yue        int inboundFailNumber = 0;
3145cc617943765df27844e459362c4bc1821305216Lixin Yue        Intent intent;
3155cc617943765df27844e459362c4bc1821305216Lixin Yue
3165cc617943765df27844e459362c4bc1821305216Lixin Yue        // If there is active transfer, no need to update complete transfer
3175cc617943765df27844e459362c4bc1821305216Lixin Yue        // notification
3185cc617943765df27844e459362c4bc1821305216Lixin Yue        if (!mUpdateCompleteNotification) {
3195cc617943765df27844e459362c4bc1821305216Lixin Yue            if (V) Log.v(TAG, "No need to update complete notification");
3205cc617943765df27844e459362c4bc1821305216Lixin Yue            return;
3215cc617943765df27844e459362c4bc1821305216Lixin Yue        }
3225cc617943765df27844e459362c4bc1821305216Lixin Yue
3235cc617943765df27844e459362c4bc1821305216Lixin Yue        // After merge complete notifications to 2 notifications, there is no
3245cc617943765df27844e459362c4bc1821305216Lixin Yue        // chance to update the active notifications to complete notifications
3255cc617943765df27844e459362c4bc1821305216Lixin Yue        // as before. So need cancel the active notification after the active
3265cc617943765df27844e459362c4bc1821305216Lixin Yue        // transfer becomes complete.
3275cc617943765df27844e459362c4bc1821305216Lixin Yue        if (mNotificationMgr != null && mActiveNotificationId != 0) {
3285cc617943765df27844e459362c4bc1821305216Lixin Yue            mNotificationMgr.cancel(mActiveNotificationId);
3295cc617943765df27844e459362c4bc1821305216Lixin Yue            if (V) Log.v(TAG, "ongoing transfer notification was removed");
3305cc617943765df27844e459362c4bc1821305216Lixin Yue        }
3315cc617943765df27844e459362c4bc1821305216Lixin Yue
3325cc617943765df27844e459362c4bc1821305216Lixin Yue        // Creating outbound notification
33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null,
3345cc617943765df27844e459362c4bc1821305216Lixin Yue                WHERE_COMPLETED_OUTBOUND, null, BluetoothShare.TIMESTAMP + " DESC");
33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (cursor == null) {
33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return;
33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3395cc617943765df27844e459362c4bc1821305216Lixin Yue        final int timestampIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP);
3405cc617943765df27844e459362c4bc1821305216Lixin Yue        final int statusIndex = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS);
34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3425cc617943765df27844e459362c4bc1821305216Lixin Yue        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
3435cc617943765df27844e459362c4bc1821305216Lixin Yue            if (cursor.isFirst()) {
3445cc617943765df27844e459362c4bc1821305216Lixin Yue                // Display the time for the latest transfer
3455cc617943765df27844e459362c4bc1821305216Lixin Yue                timeStamp = cursor.getLong(timestampIndex);
34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
3475cc617943765df27844e459362c4bc1821305216Lixin Yue            int status = cursor.getInt(statusIndex);
34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (BluetoothShare.isStatusError(status)) {
3505cc617943765df27844e459362c4bc1821305216Lixin Yue                outboundFailNumber++;
35109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
3525cc617943765df27844e459362c4bc1821305216Lixin Yue                outboundSuccNumber++;
35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
3545cc617943765df27844e459362c4bc1821305216Lixin Yue        }
3555cc617943765df27844e459362c4bc1821305216Lixin Yue        if (V) Log.v(TAG, "outbound: succ-" + outboundSuccNumber + "  fail-" + outboundFailNumber);
3565cc617943765df27844e459362c4bc1821305216Lixin Yue        cursor.close();
35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3585cc617943765df27844e459362c4bc1821305216Lixin Yue        outboundNum = outboundSuccNumber + outboundFailNumber;
3595cc617943765df27844e459362c4bc1821305216Lixin Yue        // create the outbound notification
360509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue        if (outboundNum > 0) {
361de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            Notification outNoti = new Notification();
362de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            outNoti.icon = android.R.drawable.stat_sys_upload_done;
363509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            title = mContext.getString(R.string.outbound_noti_title);
3645cc617943765df27844e459362c4bc1821305216Lixin Yue            caption = mContext.getString(R.string.noti_caption, outboundSuccNumber,
3655cc617943765df27844e459362c4bc1821305216Lixin Yue                    outboundFailNumber);
366509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            intent = new Intent(Constants.ACTION_OPEN_OUTBOUND_TRANSFER);
367509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
368de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            outNoti.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast(
3695cc617943765df27844e459362c4bc1821305216Lixin Yue                    mContext, 0, intent, 0));
370ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            intent = new Intent(Constants.ACTION_COMPLETE_HIDE);
371ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
372ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            outNoti.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
373de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            outNoti.when = timeStamp;
374de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            mNotificationMgr.notify(NOTIFICATION_ID_OUTBOUND, outNoti);
3755cc617943765df27844e459362c4bc1821305216Lixin Yue        } else {
376de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            if (mNotificationMgr != null) {
3775cc617943765df27844e459362c4bc1821305216Lixin Yue                mNotificationMgr.cancel(NOTIFICATION_ID_OUTBOUND);
3785cc617943765df27844e459362c4bc1821305216Lixin Yue                if (V) Log.v(TAG, "outbound notification was removed.");
3795cc617943765df27844e459362c4bc1821305216Lixin Yue            }
3805cc617943765df27844e459362c4bc1821305216Lixin Yue        }
3815cc617943765df27844e459362c4bc1821305216Lixin Yue
3825cc617943765df27844e459362c4bc1821305216Lixin Yue        // Creating inbound notification
3835cc617943765df27844e459362c4bc1821305216Lixin Yue        cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null,
3845cc617943765df27844e459362c4bc1821305216Lixin Yue                WHERE_COMPLETED_INBOUND, null, BluetoothShare.TIMESTAMP + " DESC");
3855cc617943765df27844e459362c4bc1821305216Lixin Yue        if (cursor == null) {
3865cc617943765df27844e459362c4bc1821305216Lixin Yue            return;
3875cc617943765df27844e459362c4bc1821305216Lixin Yue        }
38809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3895cc617943765df27844e459362c4bc1821305216Lixin Yue        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
3905cc617943765df27844e459362c4bc1821305216Lixin Yue            if (cursor.isFirst()) {
3915cc617943765df27844e459362c4bc1821305216Lixin Yue                // Display the time for the latest transfer
3925cc617943765df27844e459362c4bc1821305216Lixin Yue                timeStamp = cursor.getLong(timestampIndex);
3935cc617943765df27844e459362c4bc1821305216Lixin Yue            }
3945cc617943765df27844e459362c4bc1821305216Lixin Yue            int status = cursor.getInt(statusIndex);
3955cc617943765df27844e459362c4bc1821305216Lixin Yue
3965cc617943765df27844e459362c4bc1821305216Lixin Yue            if (BluetoothShare.isStatusError(status)) {
3975cc617943765df27844e459362c4bc1821305216Lixin Yue                inboundFailNumber++;
3985cc617943765df27844e459362c4bc1821305216Lixin Yue            } else {
3995cc617943765df27844e459362c4bc1821305216Lixin Yue                inboundSuccNumber++;
4005cc617943765df27844e459362c4bc1821305216Lixin Yue            }
40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
4025cc617943765df27844e459362c4bc1821305216Lixin Yue        if (V) Log.v(TAG, "inbound: succ-" + inboundSuccNumber + "  fail-" + inboundFailNumber);
40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        cursor.close();
4045cc617943765df27844e459362c4bc1821305216Lixin Yue
4055cc617943765df27844e459362c4bc1821305216Lixin Yue        inboundNum = inboundSuccNumber + inboundFailNumber;
4065cc617943765df27844e459362c4bc1821305216Lixin Yue        // create the inbound notification
407509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue        if (inboundNum > 0) {
408de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            Notification inNoti = new Notification();
409de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            inNoti.icon = android.R.drawable.stat_sys_download_done;
410509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            title = mContext.getString(R.string.inbound_noti_title);
4115cc617943765df27844e459362c4bc1821305216Lixin Yue            caption = mContext.getString(R.string.noti_caption, inboundSuccNumber,
4125cc617943765df27844e459362c4bc1821305216Lixin Yue                    inboundFailNumber);
413509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            intent = new Intent(Constants.ACTION_OPEN_INBOUND_TRANSFER);
414509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
415de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            inNoti.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast(
4165cc617943765df27844e459362c4bc1821305216Lixin Yue                    mContext, 0, intent, 0));
417ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            intent = new Intent(Constants.ACTION_COMPLETE_HIDE);
418ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
419ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue            inNoti.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
420de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            inNoti.when = timeStamp;
421de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            mNotificationMgr.notify(NOTIFICATION_ID_INBOUND, inNoti);
4225cc617943765df27844e459362c4bc1821305216Lixin Yue        } else {
423de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue            if (mNotificationMgr != null) {
4245cc617943765df27844e459362c4bc1821305216Lixin Yue                mNotificationMgr.cancel(NOTIFICATION_ID_INBOUND);
4255cc617943765df27844e459362c4bc1821305216Lixin Yue                if (V) Log.v(TAG, "inbound notification was removed.");
4265cc617943765df27844e459362c4bc1821305216Lixin Yue            }
4275cc617943765df27844e459362c4bc1821305216Lixin Yue        }
42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void updateIncomingFileConfirmNotification() {
43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null,
43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                WHERE_CONFIRM_PENDING, null, BluetoothShare._ID);
43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (cursor == null) {
43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return;
43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
439b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh            CharSequence title =
440b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh                    mContext.getText(R.string.incoming_file_confirm_Notification_title);
441b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh            CharSequence caption = mContext
442b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh                    .getText(R.string.incoming_file_confirm_Notification_caption);
44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int id = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID));
444dc3bacd6eb626a93f2c3c4c62b3ef6aa9e575d92Lixin Yue            long timeStamp = cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP));
44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + id);
44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Notification n = new Notification();
448464d9d216ab1a6cf192e3e526596073c7e35e4a7L.X.YUE            n.icon = R.drawable.bt_incomming_file_notification;
44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            n.flags |= Notification.FLAG_ONLY_ALERT_ONCE;
450b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh            n.flags |= Notification.FLAG_ONGOING_EVENT;
45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            n.defaults = Notification.DEFAULT_SOUND;
45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            n.tickerText = title;
453b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh
45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Intent intent = new Intent(Constants.ACTION_INCOMING_FILE_CONFIRM);
45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setData(contentUri);
4576ee2d0e0405a074cf827e0c0ac4bfbffd1850ceaLixin Yue
4586ee2d0e0405a074cf827e0c0ac4bfbffd1850ceaLixin Yue            n.when = timeStamp;
45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            n.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast(mContext, 0,
46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    intent, 0));
46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent = new Intent(Constants.ACTION_HIDE);
46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            intent.setData(contentUri);
46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            n.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mNotificationMgr.notify(id, n);
46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        cursor.close();
47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly}
472