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; 45eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Taoimport android.os.Handler; 46eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Taoimport android.os.Message; 471ac5507790a87810061a19dadec36eb328a222eaTao Liejunimport android.os.Process; 4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.util.HashMap; 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This class handles the updating of the Notification Manager for the cases 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * where there is an ongoing transfer, incoming transfer need confirm and 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * complete (successful or failed) transfer. 5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyclass BluetoothOppNotification { 5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final String TAG = "BluetoothOppNotification"; 57ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final boolean V = Constants.VERBOSE; 5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static final String status = "(" + BluetoothShare.STATUS + " == '192'" + ")"; 6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static final String visible = "(" + BluetoothShare.VISIBILITY + " IS NULL OR " 6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + BluetoothShare.VISIBILITY + " == '" + BluetoothShare.VISIBILITY_VISIBLE + "'" + ")"; 6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static final String confirm = "(" + BluetoothShare.USER_CONFIRMATION + " == '" 6509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + BluetoothShare.USER_CONFIRMATION_CONFIRMED + "' OR " 6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + BluetoothShare.USER_CONFIRMATION + " == '" 678099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen + BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED + "' OR " 688099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen + BluetoothShare.USER_CONFIRMATION + " == '" 698099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen + BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED + "'" + ")"; 708099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen 718099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen static final String not_through_handover = "(" + BluetoothShare.USER_CONFIRMATION + " != '" 728099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen + BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED + "'" + ")"; 7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static final String WHERE_RUNNING = status + " AND " + visible + " AND " + confirm; 7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 768099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen static final String WHERE_COMPLETED = BluetoothShare.STATUS + " >= '200' AND " + visible + 778099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen " AND " + not_through_handover; // Don't show handover-initiated transfers 7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 795cc617943765df27844e459362c4bc1821305216Lixin Yue private static final String WHERE_COMPLETED_OUTBOUND = WHERE_COMPLETED + " AND " + "(" 805cc617943765df27844e459362c4bc1821305216Lixin Yue + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_OUTBOUND + ")"; 815cc617943765df27844e459362c4bc1821305216Lixin Yue 825cc617943765df27844e459362c4bc1821305216Lixin Yue private static final String WHERE_COMPLETED_INBOUND = WHERE_COMPLETED + " AND " + "(" 835cc617943765df27844e459362c4bc1821305216Lixin Yue + BluetoothShare.DIRECTION + " == " + BluetoothShare.DIRECTION_INBOUND + ")"; 845cc617943765df27844e459362c4bc1821305216Lixin Yue 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static final String WHERE_CONFIRM_PENDING = BluetoothShare.USER_CONFIRMATION + " == '" 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + BluetoothShare.USER_CONFIRMATION_PENDING + "'" + " AND " + visible; 8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 881ac5507790a87810061a19dadec36eb328a222eaTao Liejun public NotificationManager mNotificationMgr; 891ac5507790a87810061a19dadec36eb328a222eaTao Liejun 901ac5507790a87810061a19dadec36eb328a222eaTao Liejun private Context mContext; 911ac5507790a87810061a19dadec36eb328a222eaTao Liejun 921ac5507790a87810061a19dadec36eb328a222eaTao Liejun private HashMap<String, NotificationItem> mNotifications; 931ac5507790a87810061a19dadec36eb328a222eaTao Liejun 941ac5507790a87810061a19dadec36eb328a222eaTao Liejun private NotificationUpdateThread mUpdateNotificationThread; 951ac5507790a87810061a19dadec36eb328a222eaTao Liejun 96eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao private int mPendingUpdate = 0; 971ac5507790a87810061a19dadec36eb328a222eaTao Liejun 985cc617943765df27844e459362c4bc1821305216Lixin Yue private static final int NOTIFICATION_ID_OUTBOUND = -1000005; 995cc617943765df27844e459362c4bc1821305216Lixin Yue 1005cc617943765df27844e459362c4bc1821305216Lixin Yue private static final int NOTIFICATION_ID_INBOUND = -1000006; 1015cc617943765df27844e459362c4bc1821305216Lixin Yue 1025cc617943765df27844e459362c4bc1821305216Lixin Yue private boolean mUpdateCompleteNotification = true; 1035cc617943765df27844e459362c4bc1821305216Lixin Yue 1045cc617943765df27844e459362c4bc1821305216Lixin Yue private int mActiveNotificationId = 0; 1055cc617943765df27844e459362c4bc1821305216Lixin Yue 10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This inner class is used to describe some properties for one transfer. 10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly static class NotificationItem { 11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int id; // This first field _id in db; 11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int direction; // to indicate sending or receiving 11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int totalCurrent = 0; // current transfer bytes 11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int totalTotal = 0; // total bytes for current transfer 11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 1185cb59523d7d7e25c58bd99c100c50e49c78481ceMatthew Xie long timeStamp = 0; // Database time stamp. Used for sorting ongoing transfers. 11974e5eba4a45ecca87eec3ac1762ca527cc614d78erik.ljungberg 12009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String description; // the text above progress bar 1218099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen 1228099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen boolean handoverInitiated = false; // transfer initiated by connection handover (eg NFC) 1237a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen 1247a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen String destination; // destination associated with this transfer 12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 12809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Constructor 129239bc526513429995c61c4148c105725c395b1a9Jackson Fan * 130239bc526513429995c61c4148c105725c395b1a9Jackson Fan * @param ctx The context to use to obtain access to the Notification 131239bc526513429995c61c4148c105725c395b1a9Jackson Fan * Service 13209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppNotification(Context ctx) { 13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = ctx; 13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotificationMgr = (NotificationManager)mContext 13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getSystemService(Context.NOTIFICATION_SERVICE); 13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifications = new HashMap<String, NotificationItem>(); 13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Update the notification ui. 14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void updateNotification() { 144c6f1bacf1d4c39d7efd5dc98004d936c18ed51f1Lixin Yue synchronized (BluetoothOppNotification.this) { 145eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mPendingUpdate++; 146eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (mPendingUpdate > 1) { 147eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (V) Log.v(TAG, "update too frequent, put in queue"); 148eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao return; 149eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 150eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (!mHandler.hasMessages(NOTIFY)) { 151eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (V) Log.v(TAG, "send message"); 152eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mHandler.sendMessage(mHandler.obtainMessage(NOTIFY)); 1531ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 1541ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 1551ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 1561ac5507790a87810061a19dadec36eb328a222eaTao Liejun 157eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao private static final int NOTIFY = 0; 158eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // Use 1 second timer to limit notification frequency. 159eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // 1. On the first notification, create the update thread. 160eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // Buffer other updates. 161eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // 2. Update thread will clear mPendingUpdate. 162eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // 3. Handler sends a delayed message to self 163eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // 4. Handler checks if there are any more updates after 1 second. 164eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao // 5. If there is an update, update it else stop. 165eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao private Handler mHandler = new Handler() { 166eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao public void handleMessage(Message msg) { 167eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao switch (msg.what) { 168eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao case NOTIFY: 169eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao synchronized (BluetoothOppNotification.this) { 170eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (mPendingUpdate > 0 && mUpdateNotificationThread == null) { 171eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (V) Log.v(TAG, "new notify threadi!"); 172eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mUpdateNotificationThread = new NotificationUpdateThread(); 173eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mUpdateNotificationThread.start(); 174eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (V) Log.v(TAG, "send delay message"); 175eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000); 176eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } else if (mPendingUpdate > 0) { 177eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (V) Log.v(TAG, "previous thread is not finished yet"); 178eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mHandler.sendMessageDelayed(mHandler.obtainMessage(NOTIFY), 1000); 179eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 180eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao break; 181eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 182eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 183eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 184eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao }; 185eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao 1861ac5507790a87810061a19dadec36eb328a222eaTao Liejun private class NotificationUpdateThread extends Thread { 1871ac5507790a87810061a19dadec36eb328a222eaTao Liejun 1881ac5507790a87810061a19dadec36eb328a222eaTao Liejun public NotificationUpdateThread() { 1891ac5507790a87810061a19dadec36eb328a222eaTao Liejun super("Notification Update Thread"); 1901ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 1911ac5507790a87810061a19dadec36eb328a222eaTao Liejun 1921ac5507790a87810061a19dadec36eb328a222eaTao Liejun @Override 1931ac5507790a87810061a19dadec36eb328a222eaTao Liejun public void run() { 1941ac5507790a87810061a19dadec36eb328a222eaTao Liejun Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 195eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao synchronized (BluetoothOppNotification.this) { 196eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao if (mUpdateNotificationThread != this) { 197eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao throw new IllegalStateException( 198eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao "multiple UpdateThreads in BluetoothOppNotification"); 1991ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 200eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mPendingUpdate = 0; 201eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao } 202eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao updateActiveNotification(); 203eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao updateCompletedNotification(); 204eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao updateIncomingFileConfirmNotification(); 205eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao synchronized (BluetoothOppNotification.this) { 206eb77c4b1d9aa71d7dd8dd934e9d1971583f9c0e2Liejun Tao mUpdateNotificationThread = null; 2071ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2081ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateActiveNotification() { 21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Active transfers 21309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null, 21409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly WHERE_RUNNING, null, BluetoothShare._ID); 21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 2195cc617943765df27844e459362c4bc1821305216Lixin Yue // If there is active transfers, then no need to update completed transfer 2205cc617943765df27844e459362c4bc1821305216Lixin Yue // notifications 2215cc617943765df27844e459362c4bc1821305216Lixin Yue if (cursor.getCount() > 0) { 2225cc617943765df27844e459362c4bc1821305216Lixin Yue mUpdateCompleteNotification = false; 2235cc617943765df27844e459362c4bc1821305216Lixin Yue } else { 2245cc617943765df27844e459362c4bc1821305216Lixin Yue mUpdateCompleteNotification = true; 2255cc617943765df27844e459362c4bc1821305216Lixin Yue } 2265cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "mUpdateCompleteNotification = " + mUpdateCompleteNotification); 2275cc617943765df27844e459362c4bc1821305216Lixin Yue 22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Collate the notifications 2295cc617943765df27844e459362c4bc1821305216Lixin Yue final int timestampIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP); 2305cc617943765df27844e459362c4bc1821305216Lixin Yue final int directionIndex = cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION); 2315cc617943765df27844e459362c4bc1821305216Lixin Yue final int idIndex = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 2325cc617943765df27844e459362c4bc1821305216Lixin Yue final int totalBytesIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES); 2335cc617943765df27844e459362c4bc1821305216Lixin Yue final int currentBytesIndex = cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES); 2345cc617943765df27844e459362c4bc1821305216Lixin Yue final int dataIndex = cursor.getColumnIndexOrThrow(BluetoothShare._DATA); 2355cc617943765df27844e459362c4bc1821305216Lixin Yue final int filenameHintIndex = cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT); 2368099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen final int confirmIndex = cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION); 2377a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen final int destinationIndex = cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION); 2385cc617943765df27844e459362c4bc1821305216Lixin Yue 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifications.clear(); 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 2415cb59523d7d7e25c58bd99c100c50e49c78481ceMatthew Xie long timeStamp = cursor.getLong(timestampIndex); 2425cc617943765df27844e459362c4bc1821305216Lixin Yue int dir = cursor.getInt(directionIndex); 2435cc617943765df27844e459362c4bc1821305216Lixin Yue int id = cursor.getInt(idIndex); 2445cc617943765df27844e459362c4bc1821305216Lixin Yue int total = cursor.getInt(totalBytesIndex); 2455cc617943765df27844e459362c4bc1821305216Lixin Yue int current = cursor.getInt(currentBytesIndex); 2468099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen int confirmation = cursor.getInt(confirmIndex); 24709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 2487a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen String destination = cursor.getString(destinationIndex); 2495cc617943765df27844e459362c4bc1821305216Lixin Yue String fileName = cursor.getString(dataIndex); 25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (fileName == null) { 2515cc617943765df27844e459362c4bc1821305216Lixin Yue fileName = cursor.getString(filenameHintIndex); 25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (fileName == null) { 25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly fileName = mContext.getString(R.string.unknown_file); 25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String batchID = Long.toString(timeStamp); 25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // sending objects in one batch has same timeStamp 26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mNotifications.containsKey(batchID)) { 26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // NOTE: currently no such case 26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Batch sending case 26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly NotificationItem item = new NotificationItem(); 26574e5eba4a45ecca87eec3ac1762ca527cc614d78erik.ljungberg item.timeStamp = timeStamp; 26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly item.id = id; 26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly item.direction = dir; 26809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (item.direction == BluetoothShare.DIRECTION_OUTBOUND) { 269239bc526513429995c61c4148c105725c395b1a9Jackson Fan item.description = mContext.getString(R.string.notification_sending, fileName); 27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (item.direction == BluetoothShare.DIRECTION_INBOUND) { 271239bc526513429995c61c4148c105725c395b1a9Jackson Fan item.description = mContext 272239bc526513429995c61c4148c105725c395b1a9Jackson Fan .getString(R.string.notification_receiving, fileName); 27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 274ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "mDirection ERROR!"); 27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly item.totalCurrent = current; 27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly item.totalTotal = total; 2788099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen item.handoverInitiated = 2798099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen confirmation == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED; 2807a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen item.destination = destination; 28109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifications.put(batchID, item); 28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 283ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "ID=" + item.id + "; batchID=" + batchID + "; totoalCurrent" 28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + item.totalCurrent + "; totalTotal=" + item.totalTotal); 28509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 28809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 28909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Add the notifications 29009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (NotificationItem item : mNotifications.values()) { 2918099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen if (item.handoverInitiated) { 2928099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen float progress = 0; 2938099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen if (item.totalTotal == -1) { 2948099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen progress = -1; 2958099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } else { 2968099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen progress = (float)item.totalCurrent / item.totalTotal; 2978099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } 2988099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen 2998099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen // Let NFC service deal with notifications for this transfer 3008099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen Intent intent = new Intent(Constants.ACTION_BT_OPP_TRANSFER_PROGRESS); 3018099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen if (item.direction == BluetoothShare.DIRECTION_INBOUND) { 3028099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 3038099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen Constants.DIRECTION_BLUETOOTH_INCOMING); 3048099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } else { 3058099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_DIRECTION, 3068099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen Constants.DIRECTION_BLUETOOTH_OUTGOING); 3078099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } 3088099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_ID, item.id); 3098099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_TRANSFER_PROGRESS, progress); 3107a4cc5c2f6ec06e8dc6f930680ce9aceff6df359Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, item.destination); 3118099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen mContext.sendBroadcast(intent, Constants.HANDOVER_STATUS_PERMISSION); 3128099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen continue; 3138099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } 31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Build the notification object 315dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby // TODO: split description into two rows with filename in second row 316dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby Notification.Builder b = new Notification.Builder(mContext); 317dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setContentTitle(item.description); 318dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setContentInfo( 319dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby BluetoothOppUtility.formatProgressText(item.totalTotal, item.totalCurrent)); 320dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setProgress(item.totalTotal, item.totalCurrent, item.totalTotal == -1); 321dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setWhen(item.timeStamp); 32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (item.direction == BluetoothShare.DIRECTION_OUTBOUND) { 323dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setSmallIcon(android.R.drawable.stat_sys_upload); 32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (item.direction == BluetoothShare.DIRECTION_INBOUND) { 325dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setSmallIcon(android.R.drawable.stat_sys_download); 32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 327ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "mDirection ERROR!"); 32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 329dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setOngoing(true); 33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Intent intent = new Intent(Constants.ACTION_LIST); 33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setData(Uri.parse(BluetoothShare.CONTENT_URI + "/" + item.id)); 33409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 335dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby b.setContentIntent(PendingIntent.getBroadcast(mContext, 0, intent, 0)); 336dec631a77ab9cc89c4d3867b80cfe300e7cf83e9Jake Hamby mNotificationMgr.notify(item.id, b.getNotification()); 3375cc617943765df27844e459362c4bc1821305216Lixin Yue 3385cc617943765df27844e459362c4bc1821305216Lixin Yue mActiveNotificationId = item.id; 33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateCompletedNotification() { 3435cc617943765df27844e459362c4bc1821305216Lixin Yue String title; 3445cc617943765df27844e459362c4bc1821305216Lixin Yue String caption; 3455cc617943765df27844e459362c4bc1821305216Lixin Yue long timeStamp = 0; 3465cc617943765df27844e459362c4bc1821305216Lixin Yue int outboundSuccNumber = 0; 3475cc617943765df27844e459362c4bc1821305216Lixin Yue int outboundFailNumber = 0; 3485cc617943765df27844e459362c4bc1821305216Lixin Yue int outboundNum; 3495cc617943765df27844e459362c4bc1821305216Lixin Yue int inboundNum; 3505cc617943765df27844e459362c4bc1821305216Lixin Yue int inboundSuccNumber = 0; 3515cc617943765df27844e459362c4bc1821305216Lixin Yue int inboundFailNumber = 0; 3525cc617943765df27844e459362c4bc1821305216Lixin Yue Intent intent; 3535cc617943765df27844e459362c4bc1821305216Lixin Yue 3545cc617943765df27844e459362c4bc1821305216Lixin Yue // If there is active transfer, no need to update complete transfer 3555cc617943765df27844e459362c4bc1821305216Lixin Yue // notification 3565cc617943765df27844e459362c4bc1821305216Lixin Yue if (!mUpdateCompleteNotification) { 3575cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "No need to update complete notification"); 3585cc617943765df27844e459362c4bc1821305216Lixin Yue return; 3595cc617943765df27844e459362c4bc1821305216Lixin Yue } 3605cc617943765df27844e459362c4bc1821305216Lixin Yue 3615cc617943765df27844e459362c4bc1821305216Lixin Yue // After merge complete notifications to 2 notifications, there is no 3625cc617943765df27844e459362c4bc1821305216Lixin Yue // chance to update the active notifications to complete notifications 3635cc617943765df27844e459362c4bc1821305216Lixin Yue // as before. So need cancel the active notification after the active 3645cc617943765df27844e459362c4bc1821305216Lixin Yue // transfer becomes complete. 3655cc617943765df27844e459362c4bc1821305216Lixin Yue if (mNotificationMgr != null && mActiveNotificationId != 0) { 3665cc617943765df27844e459362c4bc1821305216Lixin Yue mNotificationMgr.cancel(mActiveNotificationId); 3675cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "ongoing transfer notification was removed"); 3685cc617943765df27844e459362c4bc1821305216Lixin Yue } 3695cc617943765df27844e459362c4bc1821305216Lixin Yue 3705cc617943765df27844e459362c4bc1821305216Lixin Yue // Creating outbound notification 37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null, 3725cc617943765df27844e459362c4bc1821305216Lixin Yue WHERE_COMPLETED_OUTBOUND, null, BluetoothShare.TIMESTAMP + " DESC"); 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3775cc617943765df27844e459362c4bc1821305216Lixin Yue final int timestampIndex = cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP); 3785cc617943765df27844e459362c4bc1821305216Lixin Yue final int statusIndex = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS); 37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3805cc617943765df27844e459362c4bc1821305216Lixin Yue for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 3815cc617943765df27844e459362c4bc1821305216Lixin Yue if (cursor.isFirst()) { 3825cc617943765df27844e459362c4bc1821305216Lixin Yue // Display the time for the latest transfer 3835cc617943765df27844e459362c4bc1821305216Lixin Yue timeStamp = cursor.getLong(timestampIndex); 38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 3855cc617943765df27844e459362c4bc1821305216Lixin Yue int status = cursor.getInt(statusIndex); 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (BluetoothShare.isStatusError(status)) { 3885cc617943765df27844e459362c4bc1821305216Lixin Yue outboundFailNumber++; 38909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 3905cc617943765df27844e459362c4bc1821305216Lixin Yue outboundSuccNumber++; 39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 3925cc617943765df27844e459362c4bc1821305216Lixin Yue } 3935cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "outbound: succ-" + outboundSuccNumber + " fail-" + outboundFailNumber); 3945cc617943765df27844e459362c4bc1821305216Lixin Yue cursor.close(); 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3965cc617943765df27844e459362c4bc1821305216Lixin Yue outboundNum = outboundSuccNumber + outboundFailNumber; 3975cc617943765df27844e459362c4bc1821305216Lixin Yue // create the outbound notification 398509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue if (outboundNum > 0) { 399de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue Notification outNoti = new Notification(); 400de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue outNoti.icon = android.R.drawable.stat_sys_upload_done; 401509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue title = mContext.getString(R.string.outbound_noti_title); 4025cc617943765df27844e459362c4bc1821305216Lixin Yue caption = mContext.getString(R.string.noti_caption, outboundSuccNumber, 4035cc617943765df27844e459362c4bc1821305216Lixin Yue outboundFailNumber); 404509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue intent = new Intent(Constants.ACTION_OPEN_OUTBOUND_TRANSFER); 405509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 406de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue outNoti.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast( 4075cc617943765df27844e459362c4bc1821305216Lixin Yue mContext, 0, intent, 0)); 408ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue intent = new Intent(Constants.ACTION_COMPLETE_HIDE); 409ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 410ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue outNoti.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); 411de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue outNoti.when = timeStamp; 412de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue mNotificationMgr.notify(NOTIFICATION_ID_OUTBOUND, outNoti); 4135cc617943765df27844e459362c4bc1821305216Lixin Yue } else { 414de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue if (mNotificationMgr != null) { 4155cc617943765df27844e459362c4bc1821305216Lixin Yue mNotificationMgr.cancel(NOTIFICATION_ID_OUTBOUND); 4165cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "outbound notification was removed."); 4175cc617943765df27844e459362c4bc1821305216Lixin Yue } 4185cc617943765df27844e459362c4bc1821305216Lixin Yue } 4195cc617943765df27844e459362c4bc1821305216Lixin Yue 4205cc617943765df27844e459362c4bc1821305216Lixin Yue // Creating inbound notification 4215cc617943765df27844e459362c4bc1821305216Lixin Yue cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null, 4225cc617943765df27844e459362c4bc1821305216Lixin Yue WHERE_COMPLETED_INBOUND, null, BluetoothShare.TIMESTAMP + " DESC"); 4235cc617943765df27844e459362c4bc1821305216Lixin Yue if (cursor == null) { 4245cc617943765df27844e459362c4bc1821305216Lixin Yue return; 4255cc617943765df27844e459362c4bc1821305216Lixin Yue } 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4275cc617943765df27844e459362c4bc1821305216Lixin Yue for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 4285cc617943765df27844e459362c4bc1821305216Lixin Yue if (cursor.isFirst()) { 4295cc617943765df27844e459362c4bc1821305216Lixin Yue // Display the time for the latest transfer 4305cc617943765df27844e459362c4bc1821305216Lixin Yue timeStamp = cursor.getLong(timestampIndex); 4315cc617943765df27844e459362c4bc1821305216Lixin Yue } 4325cc617943765df27844e459362c4bc1821305216Lixin Yue int status = cursor.getInt(statusIndex); 4335cc617943765df27844e459362c4bc1821305216Lixin Yue 4345cc617943765df27844e459362c4bc1821305216Lixin Yue if (BluetoothShare.isStatusError(status)) { 4355cc617943765df27844e459362c4bc1821305216Lixin Yue inboundFailNumber++; 4365cc617943765df27844e459362c4bc1821305216Lixin Yue } else { 4375cc617943765df27844e459362c4bc1821305216Lixin Yue inboundSuccNumber++; 4385cc617943765df27844e459362c4bc1821305216Lixin Yue } 43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 4405cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "inbound: succ-" + inboundSuccNumber + " fail-" + inboundFailNumber); 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 4425cc617943765df27844e459362c4bc1821305216Lixin Yue 4435cc617943765df27844e459362c4bc1821305216Lixin Yue inboundNum = inboundSuccNumber + inboundFailNumber; 4445cc617943765df27844e459362c4bc1821305216Lixin Yue // create the inbound notification 445509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue if (inboundNum > 0) { 446de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue Notification inNoti = new Notification(); 447de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue inNoti.icon = android.R.drawable.stat_sys_download_done; 448509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue title = mContext.getString(R.string.inbound_noti_title); 4495cc617943765df27844e459362c4bc1821305216Lixin Yue caption = mContext.getString(R.string.noti_caption, inboundSuccNumber, 4505cc617943765df27844e459362c4bc1821305216Lixin Yue inboundFailNumber); 451509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue intent = new Intent(Constants.ACTION_OPEN_INBOUND_TRANSFER); 452509a6cd43906cce5f9bc78a83bd2058a4e5249e7Lixin Yue intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 453de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue inNoti.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast( 4545cc617943765df27844e459362c4bc1821305216Lixin Yue mContext, 0, intent, 0)); 455ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue intent = new Intent(Constants.ACTION_COMPLETE_HIDE); 456ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 457ec6f2d44491bf1e3ffa7c75875985f9c16cf721dLixin Yue inNoti.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); 458de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue inNoti.when = timeStamp; 459de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue mNotificationMgr.notify(NOTIFICATION_ID_INBOUND, inNoti); 4605cc617943765df27844e459362c4bc1821305216Lixin Yue } else { 461de773e60fed15a4ad13325089a5609c9bc6ede59Lixin Yue if (mNotificationMgr != null) { 4625cc617943765df27844e459362c4bc1821305216Lixin Yue mNotificationMgr.cancel(NOTIFICATION_ID_INBOUND); 4635cc617943765df27844e459362c4bc1821305216Lixin Yue if (V) Log.v(TAG, "inbound notification was removed."); 4645cc617943765df27844e459362c4bc1821305216Lixin Yue } 4655cc617943765df27844e459362c4bc1821305216Lixin Yue } 46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateIncomingFileConfirmNotification() { 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = mContext.getContentResolver().query(BluetoothShare.CONTENT_URI, null, 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly WHERE_CONFIRM_PENDING, null, BluetoothShare._ID); 47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 477b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh CharSequence title = 478b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh mContext.getText(R.string.incoming_file_confirm_Notification_title); 479b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh CharSequence caption = mContext 480b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh .getText(R.string.incoming_file_confirm_Notification_caption); 48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int id = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)); 482dc3bacd6eb626a93f2c3c4c62b3ef6aa9e575d92Lixin Yue long timeStamp = cursor.getLong(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)); 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + id); 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Notification n = new Notification(); 486464d9d216ab1a6cf192e3e526596073c7e35e4a7L.X.YUE n.icon = R.drawable.bt_incomming_file_notification; 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly n.flags |= Notification.FLAG_ONLY_ALERT_ONCE; 488b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh n.flags |= Notification.FLAG_ONGOING_EVENT; 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly n.defaults = Notification.DEFAULT_SOUND; 49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly n.tickerText = title; 491b0b662a98d8b7c099ee706d0e08bd239adcdffc7Jaikumar Ganesh 49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Intent intent = new Intent(Constants.ACTION_INCOMING_FILE_CONFIRM); 49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setData(contentUri); 4956ee2d0e0405a074cf827e0c0ac4bfbffd1850ceaLixin Yue 4966ee2d0e0405a074cf827e0c0ac4bfbffd1850ceaLixin Yue n.when = timeStamp; 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly n.setLatestEventInfo(mContext, title, caption, PendingIntent.getBroadcast(mContext, 0, 49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent, 0)); 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent = new Intent(Constants.ACTION_HIDE); 50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly intent.setData(contentUri); 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly n.deleteIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotificationMgr.notify(id, n); 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 510