BluetoothOppService.java revision 0f4ef70f0bc246b224f7b6da524128db89fcc8a7
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 3509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport com.google.android.collect.Lists; 3609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ObexTransport; 3709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.app.Service; 3941ef8d494511c040451f2f887cb31c3100746b61Nick Pellyimport android.bluetooth.BluetoothAdapter; 4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.BroadcastReceiver; 410a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrickimport android.content.ContentResolver; 4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentValues; 4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context; 4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent; 4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.IntentFilter; 4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.CharArrayBuffer; 4709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.ContentObserver; 4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.Cursor; 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection; 5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection.MediaScannerConnectionClient; 5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri; 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler; 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.IBinder; 5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message; 5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.PowerManager; 5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log; 5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Process; 5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.FileNotFoundException; 6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.IOException; 6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.InputStream; 6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.util.ArrayList; 6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 656769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * Performs the background Bluetooth OPP transfer. It also starts thread to 666769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * accept incoming OPP connection. 6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 6809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppService extends Service { 70ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final boolean D = Constants.DEBUG; 71ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final boolean V = Constants.VERBOSE; 7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean userAccepted = false; 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private class BluetoothShareContentObserver extends ContentObserver { 7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public BluetoothShareContentObserver() { 7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super(new Handler()); 7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onChange(boolean selfChange) { 83ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "ContentObserver received notification"); 8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateFromProvider(); 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 884852c5686229f1014e9851f4e9a3a19547581b45fredc private static final String TAG = "BtOppService"; 8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** Observer to get notified when the content observer's data changes */ 9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothShareContentObserver mObserver; 9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** Class to handle Notification Manager updates */ 9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppNotification mNotifier; 9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mPendingUpdate; 9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private UpdateThread mUpdateThread; 9909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ArrayList<BluetoothOppShareInfo> mShares; 10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ArrayList<BluetoothOppBatch> mBatchs; 10309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppTransfer mTransfer; 10509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppTransfer mServerTransfer; 10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mBatchId; 10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Array used when extracting strings from content provider 11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private CharArrayBuffer mOldChars; 11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Array used when extracting strings from content provider 11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private CharArrayBuffer mNewChars; 11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly private BluetoothAdapter mAdapter; 12109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private PowerManager mPowerManager; 12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppRfcommListener mSocketListener; 12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mListenStarted = false; 12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 1281ac5507790a87810061a19dadec36eb328a222eaTao Liejun private boolean mMediaScanInProgress; 1291ac5507790a87810061a19dadec36eb328a222eaTao Liejun 1301ac5507790a87810061a19dadec36eb328a222eaTao Liejun private int mIncomingRetries = 0; 1311ac5507790a87810061a19dadec36eb328a222eaTao Liejun 1321ac5507790a87810061a19dadec36eb328a222eaTao Liejun private ObexTransport mPendingConnection = null; 1331ac5507790a87810061a19dadec36eb328a222eaTao Liejun 13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO No support for queue incoming from multiple devices. 13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Make an array list of server session to support receiving queue from 13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * multiple devices 13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppObexServerSession mServerSession; 14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public IBinder onBind(Intent arg0) { 14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly throw new UnsupportedOperationException("Cannot bind to Bluetooth OPP Service"); 14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 14609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onCreate() { 14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onCreate(); 1494852c5686229f1014e9851f4e9a3a19547581b45fredc if (V) Log.v(TAG, "onCreate"); 1503a88b20fcd71e42451e402d27374b19eeb2ff0daNick Pelly mAdapter = BluetoothAdapter.getDefaultAdapter(); 15141ef8d494511c040451f2f887cb31c3100746b61Nick Pelly mSocketListener = new BluetoothOppRfcommListener(mAdapter); 15209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares = Lists.newArrayList(); 15309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs = Lists.newArrayList(); 15409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mObserver = new BluetoothShareContentObserver(); 15509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver); 15609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId = 1; 15709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier = new BluetoothOppNotification(this); 15809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancelAll(); 15909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.updateNotification(); 16009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 1610a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick final ContentResolver contentResolver = getContentResolver(); 1620a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick new Thread("trimDatabase") { 1630a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick public void run() { 1640a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick trimDatabase(contentResolver); 1650a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick } 1660a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick }.start(); 16709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 168f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); 169f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly registerReceiver(mBluetoothReceiver, filter); 17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 1716769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 17241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter == null) { 17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "Local BT device is not enabled"); 17409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 175ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim startListener(); 17609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 17709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 178ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) BluetoothOppPreference.getInstance(this).dump(); 17909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateFromProvider(); 18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 1838222c7902a2281929fd31e840f6012038e6fa44aLixin Yue public int onStartCommand(Intent intent, int flags, int startId) { 1844852c5686229f1014e9851f4e9a3a19547581b45fredc if (V) Log.v(TAG, "onStartCommand"); 18531ba132491053bc86d419a7d51fc04af3299c076fredc //int retCode = super.onStartCommand(intent, flags, startId); 18631ba132491053bc86d419a7d51fc04af3299c076fredc //if (retCode == START_STICKY) { 1878222c7902a2281929fd31e840f6012038e6fa44aLixin Yue if (mAdapter == null) { 1888222c7902a2281929fd31e840f6012038e6fa44aLixin Yue Log.w(TAG, "Local BT device is not enabled"); 1898222c7902a2281929fd31e840f6012038e6fa44aLixin Yue } else { 190ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim startListener(); 1918222c7902a2281929fd31e840f6012038e6fa44aLixin Yue } 1928222c7902a2281929fd31e840f6012038e6fa44aLixin Yue updateFromProvider(); 19331ba132491053bc86d419a7d51fc04af3299c076fredc //} 19431ba132491053bc86d419a7d51fc04af3299c076fredc return START_NOT_STICKY; 19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 197ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim private void startListener() { 19809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mListenStarted) { 19941ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter.isEnabled()) { 200ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim if (V) Log.v(TAG, "Starting RfcommListener"); 201ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim mHandler.sendMessage(mHandler.obtainMessage(START_LISTENER)); 20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mListenStarted = true; 20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int START_LISTENER = 1; 20809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int MEDIA_SCANNED = 2; 21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int MEDIA_SCANNED_FAILED = 3; 21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 2131ac5507790a87810061a19dadec36eb328a222eaTao Liejun private static final int MSG_INCOMING_CONNECTION_RETRY = 4; 2141ac5507790a87810061a19dadec36eb328a222eaTao Liejun 21531ba132491053bc86d419a7d51fc04af3299c076fredc private static final int STOP_LISTENER = 200; 21631ba132491053bc86d419a7d51fc04af3299c076fredc 21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mHandler = new Handler() { 21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void handleMessage(Message msg) { 22009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly switch (msg.what) { 22131ba132491053bc86d419a7d51fc04af3299c076fredc case STOP_LISTENER: 22231ba132491053bc86d419a7d51fc04af3299c076fredc mSocketListener.stop(); 22331ba132491053bc86d419a7d51fc04af3299c076fredc mListenStarted = false; 22431ba132491053bc86d419a7d51fc04af3299c076fredc synchronized (BluetoothOppService.this) { 22531ba132491053bc86d419a7d51fc04af3299c076fredc if (mUpdateThread == null) { 22631ba132491053bc86d419a7d51fc04af3299c076fredc stopSelf(); 22731ba132491053bc86d419a7d51fc04af3299c076fredc } 22831ba132491053bc86d419a7d51fc04af3299c076fredc } 22931ba132491053bc86d419a7d51fc04af3299c076fredc break; 23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case START_LISTENER: 23141ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter.isEnabled()) { 23209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 23509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED: 236ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for data uri= " 23752236de777c23788df8147de15912a57e8bc36ddTao Liejun + msg.obj.toString()); 23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(Constants.MEDIA_SCANNED, Constants.MEDIA_SCANNED_SCANNED_OK); 24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.URI, msg.obj.toString()); // update 24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.MIMETYPE, getContentResolver().getType( 24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri.parse(msg.obj.toString()))); 24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri, updateValues, null, null); 2451ac5507790a87810061a19dadec36eb328a222eaTao Liejun synchronized (BluetoothOppService.this) { 2461ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = false; 2471ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 24809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 24909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED_FAILED: 25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for MEDIA_SCANNED_FAILED"); 25109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues1 = new ContentValues(); 25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri1 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues1.put(Constants.MEDIA_SCANNED, 25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.MEDIA_SCANNED_SCANNED_FAILED); 25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri1, updateValues1, null, null); 2561ac5507790a87810061a19dadec36eb328a222eaTao Liejun synchronized (BluetoothOppService.this) { 2571ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = false; 2581ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2591ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 2601ac5507790a87810061a19dadec36eb328a222eaTao Liejun case BluetoothOppRfcommListener.MSG_INCOMING_BTOPP_CONNECTION: 261ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Get incoming connection"); 2621ac5507790a87810061a19dadec36eb328a222eaTao Liejun ObexTransport transport = (ObexTransport)msg.obj; 2631ac5507790a87810061a19dadec36eb328a222eaTao Liejun /* 2641ac5507790a87810061a19dadec36eb328a222eaTao Liejun * Strategy for incoming connections: 2651ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 1. If there is no ongoing transfer, no on-hold connection, start it 2661ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 2. If there is ongoing transfer, hold it for 20 seconds(1 seconds * 20 times) 2671ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 3. If there is on-hold connection, reject directly 2681ac5507790a87810061a19dadec36eb328a222eaTao Liejun */ 2691ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mBatchs.size() == 0 && mPendingConnection == null) { 2701ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "Start Obex Server"); 2711ac5507790a87810061a19dadec36eb328a222eaTao Liejun createServerSession(transport); 2721ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2731ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mPendingConnection != null) { 2741ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.w(TAG, "OPP busy! Reject connection"); 2751ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 2761ac5507790a87810061a19dadec36eb328a222eaTao Liejun transport.close(); 2771ac5507790a87810061a19dadec36eb328a222eaTao Liejun } catch (IOException e) { 2781ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.e(TAG, "close tranport error"); 2791ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 280a930b6831d0c70b6c5d34e548e6b1dceaa6529a0Mohammad Shamsi } else if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) { 281888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun Log.i(TAG, "Start Obex Server in TCP DEBUG mode"); 282888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun createServerSession(transport); 2831ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2841ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "OPP busy! Retry after 1 second"); 2851ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = mIncomingRetries + 1; 2861ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = transport; 2871ac5507790a87810061a19dadec36eb328a222eaTao Liejun Message msg1 = Message.obtain(mHandler); 2881ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg1.what = MSG_INCOMING_CONNECTION_RETRY; 2891ac5507790a87810061a19dadec36eb328a222eaTao Liejun mHandler.sendMessageDelayed(msg1, 1000); 2901ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2911ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2921ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 2931ac5507790a87810061a19dadec36eb328a222eaTao Liejun case MSG_INCOMING_CONNECTION_RETRY: 2941ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mBatchs.size() == 0) { 2951ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "Start Obex Server"); 2961ac5507790a87810061a19dadec36eb328a222eaTao Liejun createServerSession(mPendingConnection); 2971ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = 0; 2981ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = null; 2991ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 3001ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mIncomingRetries == 20) { 3011ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.w(TAG, "Retried 20 seconds, reject connection"); 3021ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 3031ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection.close(); 3041ac5507790a87810061a19dadec36eb328a222eaTao Liejun } catch (IOException e) { 3051ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.e(TAG, "close tranport error"); 3061ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 3071ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = 0; 3081ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = null; 3091ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 3101ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "OPP busy! Retry after 1 second"); 3111ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = mIncomingRetries + 1; 3121ac5507790a87810061a19dadec36eb328a222eaTao Liejun Message msg2 = Message.obtain(mHandler); 3131ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg2.what = MSG_INCOMING_CONNECTION_RETRY; 3141ac5507790a87810061a19dadec36eb328a222eaTao Liejun mHandler.sendMessageDelayed(msg2, 1000); 3151ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 3161ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 3171ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void startSocketListener() { 32309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 324ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "start RfcommListener"); 3251ac5507790a87810061a19dadec36eb328a222eaTao Liejun mSocketListener.start(mHandler); 326ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "RfcommListener started"); 32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onDestroy() { 3314852c5686229f1014e9851f4e9a3a19547581b45fredc if (V) Log.v(TAG, "onDestroy"); 33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onDestroy(); 33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().unregisterContentObserver(mObserver); 334f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly unregisterReceiver(mBluetoothReceiver); 33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 3363fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan 3373fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan if(mBatchs != null) { 3383fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan mBatchs.clear(); 3393fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan } 3403fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan if(mShares != null) { 3413fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan mShares.clear(); 3423fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan } 3433fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan if(mHandler != null) { 3443fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan mHandler.removeCallbacksAndMessages(null); 3453fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan } 34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* suppose we auto accept an incoming OPUSH connection */ 34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void createServerSession(ObexTransport transport) { 35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession = new BluetoothOppObexServerSession(this, transport); 35109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession.preStart(); 352ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Get ServerSession " + mServerSession.toString() 35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for incoming connection" + transport.toString()); 35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 356f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() { 35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onReceive(Context context, Intent intent) { 35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String action = intent.getAction(); 36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 361f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 362613bae227d65f61903e196944a9c718b4394f25aNick Pelly switch (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 363f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly case BluetoothAdapter.STATE_ON: 364ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, 36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "Receiver BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON"); 36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 368f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly case BluetoothAdapter.STATE_TURNING_OFF: 369ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Receiver DISABLED_ACTION "); 37031ba132491053bc86d419a7d51fc04af3299c076fredc //FIX: Don't block main thread 37131ba132491053bc86d419a7d51fc04af3299c076fredc /* 37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mListenStarted = false; 3746769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37931ba132491053bc86d419a7d51fc04af3299c076fredc */ 38031ba132491053bc86d419a7d51fc04af3299c076fredc mHandler.sendMessage(mHandler.obtainMessage(STOP_LISTENER)); 38131ba132491053bc86d419a7d51fc04af3299c076fredc 38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 38809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateFromProvider() { 3896769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 39009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = true; 39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 39209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = new UpdateThread(); 39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread.start(); 39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private class UpdateThread extends Thread { 39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public UpdateThread() { 40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super("Bluetooth Share Service"); 40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 40409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void run() { 40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4071ac5507790a87810061a19dadec36eb328a222eaTao Liejun boolean keepService = false; 40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (;;) { 4096769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread != this) { 41109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly throw new IllegalStateException( 41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "multiple UpdateThreads in BluetoothOppService"); 41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 414ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "pendingUpdate is " + mPendingUpdate + " keepUpdateThread is " 4151ac5507790a87810061a19dadec36eb328a222eaTao Liejun + keepService + " sListenStarted is " + mListenStarted); 41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mPendingUpdate) { 41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = null; 4181ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (!keepService && !mListenStarted) { 41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = false; 42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = getContentResolver().query(BluetoothShare.CONTENT_URI, null, null, 42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly null, BluetoothShare._ID); 42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToFirst(); 43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayPos = 0; 43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4371ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = false; 43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean isAfterLast = cursor.isAfterLast(); 43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int idColumn = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Walk the cursor and the local array to keep them in sync. The 44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * key to the algorithm is that the ids are unique and sorted 44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * both in the cursor and in the array, so that they can be 44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed in order in both sources at the same time: at each 44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * step, both sources point to the lowest id that hasn't been 44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed from that source, and the algorithm processes the 44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * lowest id from those two possibilities. At each step: -If the 44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * array contains an entry that's not in the cursor, remove the 45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * entry, move to next entry in the array. -If the array 45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's in the cursor, nothing to do, move 45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * to next cursor row and next array entry. -If the cursor 45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's not in the array, insert a new entry 45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * in the array, move to next cursor row and next array entry. 45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (!isAfterLast || arrayPos < mShares.size()) { 45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (isAfterLast) { 45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // We're beyond the end of the cursor but there's still 45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // some 46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // stuff in the local array, which can only be junk 46103f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh if (V) Log.v(TAG, "Array update: trimming " + 462ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly mShares.get(arrayPos).mId + " @ " + arrayPos); 46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); // this advances in the array 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int id = cursor.getInt(idColumn); 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayPos == mShares.size()) { 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 473ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: inserting " + id + " @ " + arrayPos); 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 4751ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 4781ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 4811ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayId = mShares.get(arrayPos).mId; 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayId < id) { 491ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: removing " + arrayId + " @ " 49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + arrayPos); 49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (arrayId == id) { 49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor row already exists in the stored 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateShare(cursor, arrayPos, userAccepted); 50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 5021ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 5051ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 5081ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor entry didn't exist in the stored 51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 517ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: appending " + id + " @ " + arrayPos); 51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 5211ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 5241ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 5271ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.updateNotification(); 53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void insertShare(Cursor cursor, int arrayPos) { 546ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby String uriString = cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.URI)); 547ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby Uri uri; 548ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby if (uriString != null) { 549ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby uri = Uri.parse(uriString); 550ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby Log.d(TAG, "insertShare parsed URI: " + uri); 551ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby } else { 552ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby uri = null; 553ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby Log.e(TAG, "insertShare found null URI at cursor!"); 554ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby } 55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppShareInfo info = new BluetoothOppShareInfo( 55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)), 557ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby uri, 55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT)), 55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare._DATA)), 56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.MIMETYPE)), 56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)), 56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION)), 56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)), 56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)), 56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)), 56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)), 56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)), 56809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)), 56909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 571ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 57209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service adding new entry"); 57309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "ID : " + info.mId); 57409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Log.v(TAG, "URI : " + ((info.mUri != null) ? "yes" : "no")); 57509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "URI : " + info.mUri); 57609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "HINT : " + info.mHint); 57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "FILENAME: " + info.mFilename); 57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MIMETYPE: " + info.mMimetype); 57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DIRECTION: " + info.mDirection); 58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DESTINAT: " + info.mDestination); 58109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "VISIBILI: " + info.mVisibility); 58209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CONFIRM : " + info.mConfirm); 58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "STATUS : " + info.mStatus); 58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TOTAL : " + info.mTotalBytes); 58509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CURRENT : " + info.mCurrentBytes); 58609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TIMESTAMP : " + info.mTimestamp); 58709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "SCANNED : " + info.mMediaScanned); 58809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 58909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 59009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.add(arrayPos, info); 59109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 59209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Mark the info as failed if it's in invalid status */ 59309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isObsolete()) { 59409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_UNKNOWN_ERROR); 59509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 59609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 59709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Add info into a batch. The logic is 59809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Only add valid and readyToStart info 59909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) If there is no batch, create a batch and insert this transfer into batch, 60009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * then run the batch 60109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If there is existing batch and timestamp match, insert transfer into batch 60209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 4) If there is existing batch and timestamp does not match, create a new batch and 60309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * put in queue 60409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 60509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 60609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isReadyToStart()) { 60709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* check if the file exists */ 609ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby BluetoothOppSendFileInfo sendFileInfo = BluetoothOppUtility.getSendFileInfo( 610ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby info.mUri); 611ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby if (sendFileInfo == null || sendFileInfo.mInputStream == null) { 61209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId); 61309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 614ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby BluetoothOppUtility.closeSendFileInfo(info.mUri); 61509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 61609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 61709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 61809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() == 0) { 61909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 62009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 62109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 62209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 62309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 624ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 62509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for OUTBOUND info " + info.mId); 62609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch); 62709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 628ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 62909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for INBOUND info " + info.mId); 63009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, 63109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession); 63209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 63309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 63409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND && mTransfer != null) { 635ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service start transfer new Batch " + newBatch.mId 63609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 63709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 63809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND 63909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && mServerTransfer != null) { 640ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service start server transfer new Batch " + newBatch.mId 64109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 64209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.start(); 64309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 64509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 64609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 64709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 648ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service add info " + info.mId + " to existing batch " 64909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mBatchs.get(i).mId); 65009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.get(i).addShare(info); 65109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 652888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun // There is ongoing batch 65309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 65409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 65509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 65609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 657888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (V) Log.v(TAG, "Service add new Batch " + newBatch.mId + " for info " + 658888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun info.mId); 659888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) { 660888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun // only allow concurrent serverTransfer in debug mode 661888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 662888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (V) Log.v(TAG, "TCP_DEBUG start server transfer new Batch " + 663888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun newBatch.mId + " for info " + info.mId); 664888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, 665888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun newBatch, mServerSession); 666888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun mServerTransfer.start(); 667888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun } 668888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun } 66909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateShare(Cursor cursor, int arrayPos, boolean userAccepted) { 6756769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 67609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS); 67709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)); 679ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby if (info.mUri != null) { 680ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby info.mUri = Uri.parse(stringFromCursor(info.mUri.toString(), cursor, 681ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby BluetoothShare.URI)); 682ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby } else { 6830f4ef70f0bc246b224f7b6da524128db89fcc8a7Matthew Xie Log.w(TAG, "updateShare() called for ID " + info.mId + " with null URI"); 684ee52ddf33a0ce2cf89cc028136f60ae600c45de5Jake Hamby } 68509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mHint = stringFromCursor(info.mHint, cursor, BluetoothShare.FILENAME_HINT); 68609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mFilename = stringFromCursor(info.mFilename, cursor, BluetoothShare._DATA); 68709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMimetype = stringFromCursor(info.mMimetype, cursor, BluetoothShare.MIMETYPE); 68809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDirection = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)); 68909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDestination = stringFromCursor(info.mDestination, cursor, BluetoothShare.DESTINATION); 69009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)); 69109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 69209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean confirmed = false; 69309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newConfirm = cursor.getInt(cursor 69409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 69509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 69609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mVisibility == BluetoothShare.VISIBILITY_VISIBLE 69709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newVisibility != BluetoothShare.VISIBILITY_VISIBLE 69809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && (BluetoothShare.isStatusCompleted(info.mStatus) || newConfirm == BluetoothShare.USER_CONFIRMATION_PENDING)) { 69909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 70009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 70109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 70209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mVisibility = newVisibility; 70309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 70409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mConfirm == BluetoothShare.USER_CONFIRMATION_PENDING 70509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newConfirm != BluetoothShare.USER_CONFIRMATION_PENDING) { 70609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly confirmed = true; 70709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 70809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mConfirm = cursor.getInt(cursor 70909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 71009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newStatus = cursor.getInt(statusColumn); 71109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 71209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!BluetoothShare.isStatusCompleted(info.mStatus) 71309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && BluetoothShare.isStatusCompleted(newStatus)) { 71409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 71509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 71609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 71709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mStatus = newStatus; 71809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)); 71909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mCurrentBytes = cursor.getInt(cursor 72009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)); 72109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTimestamp = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)); 72209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMediaScanned = (cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 72309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 72409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (confirmed) { 725ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service handle info " + info.mId + " confirmed"); 72609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Inbounds transfer get user confirmation, so we start it */ 727df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun int i = findBatchWithTimeStamp(info.mTimestamp); 7289d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (i != -1) { 7299d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothOppBatch batch = mBatchs.get(i); 7309d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (mServerTransfer != null && batch.mId == mServerTransfer.getBatchId()) { 7319d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.setConfirmed(); 7329d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } //TODO need to think about else 7339d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 73409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 73609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 73709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 73809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mStatus == Constants.BATCH_STATUS_FINISHED 73909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly || batch.mStatus == Constants.BATCH_STATUS_FAILED) { 740ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Batch " + batch.mId + " is finished"); 74109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 74209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mTransfer == null) { 74309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mTransfer is null"); 74409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mTransfer.getBatchId()) { 74509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.stop(); 74609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 74709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 74809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mTransfer id " + mTransfer.getBatchId()); 74909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 7509d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mTransfer = null; 75109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 75209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mServerTransfer == null) { 75309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mServerTransfer is null"); 75409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mServerTransfer.getBatchId()) { 75509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.stop(); 75609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 75709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 75809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mServerTransfer id " 75909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mServerTransfer.getBatchId()); 76009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 7619d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer = null; 76209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 76409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 76809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 76909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Removes the local copy of the info about a share. 77009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 77109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void deleteShare(int arrayPos) { 7726769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 77309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 77409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 77509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Delete arrayPos from a batch. The logic is 77609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Search existing batch for the info 77709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) cancel the batch 77809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If the batch become empty delete the batch 77909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 78009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 78109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 78209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 78309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.hasShare(info)) { 784ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service cancel batch for share " + info.mId); 78509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly batch.cancelBatch(); 78609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 78709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.isEmpty()) { 788ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service remove batch " + batch.mId); 78909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 79009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.remove(arrayPos); 79309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 79509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private String stringFromCursor(String old, Cursor cursor, String column) { 79609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int index = cursor.getColumnIndexOrThrow(column); 79709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (old == null) { 79809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 79909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mNewChars == null) { 80109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNewChars = new CharArrayBuffer(128); 80209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.copyStringToBuffer(index, mNewChars); 80409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int length = mNewChars.sizeCopied; 80509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (length != old.length()) { 80609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 80709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mOldChars == null || mOldChars.sizeCopied < length) { 80909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mOldChars = new CharArrayBuffer(length); 81009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] oldArray = mOldChars.data; 81209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] newArray = mNewChars.data; 81309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly old.getChars(0, length, oldArray, 0); 81409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = length - 1; i >= 0; --i) { 81509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (oldArray[i] != newArray[i]) { 81609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return new String(newArray, 0, length); 81709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return old; 82009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 82209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int findBatchWithTimeStamp(long timestamp) { 82309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = mBatchs.size() - 1; i >= 0; i--) { 82409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.get(i).mTimestamp == timestamp) { 82509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return i; 82609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return -1; 82909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 83109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void removeBatch(BluetoothOppBatch batch) { 832ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Remove batch " + batch.mId); 83309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.remove(batch); 8349d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothOppBatch nextBatch; 83509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() > 0) { 83609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = 0; i < mBatchs.size(); i++) { 83709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // we have a running batch 8389d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun nextBatch = mBatchs.get(i); 8399d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.mStatus == Constants.BATCH_STATUS_RUNNING) { 84009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 84109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 8421ac5507790a87810061a19dadec36eb328a222eaTao Liejun // just finish a transfer, start pending outbound transfer 8439d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 8449d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "Start pending outbound batch " + nextBatch.mId); 8459d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch); 84609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 84709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 8489d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } else if (nextBatch.mDirection == BluetoothShare.DIRECTION_INBOUND 8499d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun && mServerSession != null) { 8509d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun // have to support pending inbound transfer 8519d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun // if an outbound transfer and incoming socket happens together 8529d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "Start pending inbound batch " + nextBatch.mId); 8539d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch, 8549d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerSession); 8559d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.start(); 8569d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.getPendingShare().mConfirm == 8579d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothShare.USER_CONFIRMATION_CONFIRMED) { 8589d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.setConfirmed(); 8599d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 8609d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun return; 86109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 86709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean needAction(int arrayPos) { 8686769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 86909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (BluetoothShare.isStatusCompleted(info.mStatus)) { 87009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return false; 87109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return true; 87309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 87509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean visibleNotification(int arrayPos) { 8766769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 87709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return info.hasCompletionNotification(); 87809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 88009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean scanFile(Cursor cursor, int arrayPos) { 8816769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 8826769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 883ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Scanning file " + info.mFilename); 8841ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (!mMediaScanInProgress) { 8851ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = true; 8861ac5507790a87810061a19dadec36eb328a222eaTao Liejun new MediaScannerNotifier(this, info, mHandler); 8871ac5507790a87810061a19dadec36eb328a222eaTao Liejun return true; 8881ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 8891ac5507790a87810061a19dadec36eb328a222eaTao Liejun return false; 8901ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 89109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 89209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 89309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 89409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean shouldScanFile(int arrayPos) { 8956769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 8961ac5507790a87810061a19dadec36eb328a222eaTao Liejun return BluetoothShare.isStatusSuccess(info.mStatus) 897d5e1472188b7e21123a02339ed8766256aa8f630Martijn Coenen && info.mDirection == BluetoothShare.DIRECTION_INBOUND && !info.mMediaScanned && 898d5e1472188b7e21123a02339ed8766256aa8f630Martijn Coenen info.mConfirm != BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED; 89909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 90009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9010a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick // Run in a background thread at boot. 9020a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick private static void trimDatabase(ContentResolver contentResolver) { 903389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String INVISIBLE = BluetoothShare.VISIBILITY + "=" + 904389f6dd45f7a45b12af847a510086125777e1198Lixin Yue BluetoothShare.VISIBILITY_HIDDEN; 905389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 906389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // remove the invisible/complete/outbound shares 907389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INVISIBLE_COMPLETE_OUTBOUND = BluetoothShare.DIRECTION + "=" 908389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_OUTBOUND + " AND " + BluetoothShare.STATUS + ">=" 909389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 9100a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick int delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 911389f6dd45f7a45b12af847a510086125777e1198Lixin Yue WHERE_INVISIBLE_COMPLETE_OUTBOUND, null); 912389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (V) Log.v(TAG, "Deleted complete outbound shares, number = " + delNum); 913389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 914389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // remove the invisible/finished/inbound/failed shares 915389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED = BluetoothShare.DIRECTION + "=" 916389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + ">" 917389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 9180a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 919389f6dd45f7a45b12af847a510086125777e1198Lixin Yue WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED, null); 920389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (V) Log.v(TAG, "Deleted complete inbound failed shares, number = " + delNum); 921389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 922389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // Only keep the inbound and successful shares for LiverFolder use 923389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // Keep the latest 1000 to easy db query 924389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INBOUND_SUCCESS = BluetoothShare.DIRECTION + "=" 925389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + "=" 926389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 9270a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick Cursor cursor = contentResolver.query(BluetoothShare.CONTENT_URI, new String[] { 92809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothShare._ID 929389f6dd45f7a45b12af847a510086125777e1198Lixin Yue }, WHERE_INBOUND_SUCCESS, null, BluetoothShare._ID); // sort by id 930389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 93109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 93209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 93309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 934389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 935389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int recordNum = cursor.getCount(); 936389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (recordNum > Constants.MAX_RECORDS_IN_DATABASE) { 937389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int numToDelete = recordNum - Constants.MAX_RECORDS_IN_DATABASE; 93875fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue 93975fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue if (cursor.moveToPosition(numToDelete)) { 940389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 94175fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue long id = cursor.getLong(columnId); 9420a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 94375fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue BluetoothShare._ID + " < " + id, null); 94475fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue if (V) Log.v(TAG, "Deleted old inbound success share: " + delNum); 94509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 94609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 94709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 94809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 94909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 95009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static class MediaScannerNotifier implements MediaScannerConnectionClient { 95109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 95209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private MediaScannerConnection mConnection; 95309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 95409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppShareInfo mInfo; 95509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 95609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Context mContext; 95709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 95809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mCallback; 95909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 96009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public MediaScannerNotifier(Context context, BluetoothOppShareInfo info, Handler handler) { 96109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = context; 96209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo = info; 96309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback = handler; 96409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection = new MediaScannerConnection(mContext, this); 965ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Connecting to MediaScannerConnection "); 96609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.connect(); 96709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 96909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onMediaScannerConnected() { 970ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "MediaScannerConnection onMediaScannerConnected"); 97109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype); 97209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 97309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 97409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onScanCompleted(String path, Uri uri) { 97509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 976ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 97709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection onScanCompleted"); 97809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection path is " + path); 97909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection Uri is " + uri); 98009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 98109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (uri != null) { 98209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 98309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 98409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED; 98509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 98609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = uri; 98709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 98809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 98909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 99009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 99109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED_FAILED; 99209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 99309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 99409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 99509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (Exception ex) { 99609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "!!!MediaScannerConnection exception: " + ex); 99709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } finally { 998ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "MediaScannerConnection disconnect"); 99909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.disconnect(); 100009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 100109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 100209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 100309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 1004