BluetoothOppService.java revision ef697b0b9a74e15b5003e134307e72b20b48de12
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 8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final String TAG = "BtOpp Service"; 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(); 149ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service 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) { 1848222c7902a2281929fd31e840f6012038e6fa44aLixin Yue if (V) Log.v(TAG, "Service onStartCommand"); 1858222c7902a2281929fd31e840f6012038e6fa44aLixin Yue int retCode = super.onStartCommand(intent, flags, startId); 1868222c7902a2281929fd31e840f6012038e6fa44aLixin Yue 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(); 19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 1948222c7902a2281929fd31e840f6012038e6fa44aLixin Yue return retCode; 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 21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mHandler = new Handler() { 21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void handleMessage(Message msg) { 21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly switch (msg.what) { 21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case START_LISTENER: 22041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter.isEnabled()) { 22109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 22309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 22409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED: 225ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for data uri= " 22652236de777c23788df8147de15912a57e8bc36ddTao Liejun + msg.obj.toString()); 22709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(Constants.MEDIA_SCANNED, Constants.MEDIA_SCANNED_SCANNED_OK); 23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.URI, msg.obj.toString()); // update 23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.MIMETYPE, getContentResolver().getType( 23209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri.parse(msg.obj.toString()))); 23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri, updateValues, null, null); 2341ac5507790a87810061a19dadec36eb328a222eaTao Liejun synchronized (BluetoothOppService.this) { 2351ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = false; 2361ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED_FAILED: 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for MEDIA_SCANNED_FAILED"); 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues1 = new ContentValues(); 24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri1 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues1.put(Constants.MEDIA_SCANNED, 24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.MEDIA_SCANNED_SCANNED_FAILED); 24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri1, updateValues1, null, null); 2451ac5507790a87810061a19dadec36eb328a222eaTao Liejun synchronized (BluetoothOppService.this) { 2461ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = false; 2471ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2481ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 2491ac5507790a87810061a19dadec36eb328a222eaTao Liejun case BluetoothOppRfcommListener.MSG_INCOMING_BTOPP_CONNECTION: 250ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Get incoming connection"); 2511ac5507790a87810061a19dadec36eb328a222eaTao Liejun ObexTransport transport = (ObexTransport)msg.obj; 2521ac5507790a87810061a19dadec36eb328a222eaTao Liejun /* 2531ac5507790a87810061a19dadec36eb328a222eaTao Liejun * Strategy for incoming connections: 2541ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 1. If there is no ongoing transfer, no on-hold connection, start it 2551ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 2. If there is ongoing transfer, hold it for 20 seconds(1 seconds * 20 times) 2561ac5507790a87810061a19dadec36eb328a222eaTao Liejun * 3. If there is on-hold connection, reject directly 2571ac5507790a87810061a19dadec36eb328a222eaTao Liejun */ 2581ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mBatchs.size() == 0 && mPendingConnection == null) { 2591ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "Start Obex Server"); 2601ac5507790a87810061a19dadec36eb328a222eaTao Liejun createServerSession(transport); 2611ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2621ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mPendingConnection != null) { 2631ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.w(TAG, "OPP busy! Reject connection"); 2641ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 2651ac5507790a87810061a19dadec36eb328a222eaTao Liejun transport.close(); 2661ac5507790a87810061a19dadec36eb328a222eaTao Liejun } catch (IOException e) { 2671ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.e(TAG, "close tranport error"); 2681ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 269a930b6831d0c70b6c5d34e548e6b1dceaa6529a0Mohammad Shamsi } else if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) { 270888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun Log.i(TAG, "Start Obex Server in TCP DEBUG mode"); 271888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun createServerSession(transport); 2721ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2731ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "OPP busy! Retry after 1 second"); 2741ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = mIncomingRetries + 1; 2751ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = transport; 2761ac5507790a87810061a19dadec36eb328a222eaTao Liejun Message msg1 = Message.obtain(mHandler); 2771ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg1.what = MSG_INCOMING_CONNECTION_RETRY; 2781ac5507790a87810061a19dadec36eb328a222eaTao Liejun mHandler.sendMessageDelayed(msg1, 1000); 2791ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2801ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2811ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 2821ac5507790a87810061a19dadec36eb328a222eaTao Liejun case MSG_INCOMING_CONNECTION_RETRY: 2831ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mBatchs.size() == 0) { 2841ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "Start Obex Server"); 2851ac5507790a87810061a19dadec36eb328a222eaTao Liejun createServerSession(mPendingConnection); 2861ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = 0; 2871ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = null; 2881ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2891ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mIncomingRetries == 20) { 2901ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.w(TAG, "Retried 20 seconds, reject connection"); 2911ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 2921ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection.close(); 2931ac5507790a87810061a19dadec36eb328a222eaTao Liejun } catch (IOException e) { 2941ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.e(TAG, "close tranport error"); 2951ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 2961ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = 0; 2971ac5507790a87810061a19dadec36eb328a222eaTao Liejun mPendingConnection = null; 2981ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 2991ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.i(TAG, "OPP busy! Retry after 1 second"); 3001ac5507790a87810061a19dadec36eb328a222eaTao Liejun mIncomingRetries = mIncomingRetries + 1; 3011ac5507790a87810061a19dadec36eb328a222eaTao Liejun Message msg2 = Message.obtain(mHandler); 3021ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg2.what = MSG_INCOMING_CONNECTION_RETRY; 3031ac5507790a87810061a19dadec36eb328a222eaTao Liejun mHandler.sendMessageDelayed(msg2, 1000); 3041ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 3051ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 3061ac5507790a87810061a19dadec36eb328a222eaTao Liejun break; 30709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 30809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 30909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 31009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 31109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void startSocketListener() { 31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 313ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "start RfcommListener"); 3141ac5507790a87810061a19dadec36eb328a222eaTao Liejun mSocketListener.start(mHandler); 315ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "RfcommListener started"); 31609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onDestroy() { 320ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service onDestroy"); 32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onDestroy(); 32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().unregisterContentObserver(mObserver); 323f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly unregisterReceiver(mBluetoothReceiver); 32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 32509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* suppose we auto accept an incoming OPUSH connection */ 32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void createServerSession(ObexTransport transport) { 32909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession = new BluetoothOppObexServerSession(this, transport); 33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession.preStart(); 331ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Get ServerSession " + mServerSession.toString() 33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for incoming connection" + transport.toString()); 33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 33409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 335f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() { 33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onReceive(Context context, Intent intent) { 33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String action = intent.getAction(); 33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 340f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 341613bae227d65f61903e196944a9c718b4394f25aNick Pelly switch (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 342f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly case BluetoothAdapter.STATE_ON: 343ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, 34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "Receiver BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON"); 34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 347f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly case BluetoothAdapter.STATE_TURNING_OFF: 348ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Receiver DISABLED_ACTION "); 34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mListenStarted = false; 3516769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 35209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateFromProvider() { 3636769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = true; 36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = new UpdateThread(); 36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread.start(); 36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private class UpdateThread extends Thread { 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public UpdateThread() { 37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super("Bluetooth Share Service"); 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void run() { 37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3811ac5507790a87810061a19dadec36eb328a222eaTao Liejun boolean keepService = false; 38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (;;) { 3836769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread != this) { 38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly throw new IllegalStateException( 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "multiple UpdateThreads in BluetoothOppService"); 38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 388ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "pendingUpdate is " + mPendingUpdate + " keepUpdateThread is " 3891ac5507790a87810061a19dadec36eb328a222eaTao Liejun + keepService + " sListenStarted is " + mListenStarted); 39009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mPendingUpdate) { 39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = null; 3921ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (!keepService && !mListenStarted) { 39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = false; 39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = getContentResolver().query(BluetoothShare.CONTENT_URI, null, null, 40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly null, BluetoothShare._ID); 40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 40409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToFirst(); 40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayPos = 0; 41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4111ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = false; 41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean isAfterLast = cursor.isAfterLast(); 41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int idColumn = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Walk the cursor and the local array to keep them in sync. The 41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * key to the algorithm is that the ids are unique and sorted 41809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * both in the cursor and in the array, so that they can be 41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed in order in both sources at the same time: at each 42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * step, both sources point to the lowest id that hasn't been 42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed from that source, and the algorithm processes the 42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * lowest id from those two possibilities. At each step: -If the 42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * array contains an entry that's not in the cursor, remove the 42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * entry, move to next entry in the array. -If the array 42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's in the cursor, nothing to do, move 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * to next cursor row and next array entry. -If the cursor 42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's not in the array, insert a new entry 42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * in the array, move to next cursor row and next array entry. 42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (!isAfterLast || arrayPos < mShares.size()) { 43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (isAfterLast) { 43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // We're beyond the end of the cursor but there's still 43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // some 43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // stuff in the local array, which can only be junk 43503f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh if (V) Log.v(TAG, "Array update: trimming " + 436ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly mShares.get(arrayPos).mId + " @ " + arrayPos); 43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); // this advances in the array 44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int id = cursor.getInt(idColumn); 44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayPos == mShares.size()) { 44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 447ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: inserting " + id + " @ " + arrayPos); 44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 4491ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 4521ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 4551ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayId = mShares.get(arrayPos).mId; 46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayId < id) { 465ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: removing " + arrayId + " @ " 46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + arrayPos); 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); 47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (arrayId == id) { 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor row already exists in the stored 47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateShare(cursor, arrayPos, userAccepted); 47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 4761ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 4791ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 4821ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor entry didn't exist in the stored 49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 491ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Array update: appending " + id + " @ " + arrayPos); 49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 4951ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 4981ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 5011ac5507790a87810061a19dadec36eb328a222eaTao Liejun keepService = true; 50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.updateNotification(); 51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void insertShare(Cursor cursor, int arrayPos) { 52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppShareInfo info = new BluetoothOppShareInfo( 52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)), 52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.URI)), 52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT)), 52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare._DATA)), 52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.MIMETYPE)), 52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)), 52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION)), 52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)), 52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)), 53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)), 53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)), 53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)), 53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)), 53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 536ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service adding new entry"); 53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "ID : " + info.mId); 53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Log.v(TAG, "URI : " + ((info.mUri != null) ? "yes" : "no")); 54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "URI : " + info.mUri); 54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "HINT : " + info.mHint); 54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "FILENAME: " + info.mFilename); 54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MIMETYPE: " + info.mMimetype); 54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DIRECTION: " + info.mDirection); 54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DESTINAT: " + info.mDestination); 54609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "VISIBILI: " + info.mVisibility); 54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CONFIRM : " + info.mConfirm); 54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "STATUS : " + info.mStatus); 54909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TOTAL : " + info.mTotalBytes); 55009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CURRENT : " + info.mCurrentBytes); 55109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TIMESTAMP : " + info.mTimestamp); 55209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "SCANNED : " + info.mMediaScanned); 55309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 55409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.add(arrayPos, info); 55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Mark the info as failed if it's in invalid status */ 55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isObsolete()) { 55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_UNKNOWN_ERROR); 56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Add info into a batch. The logic is 56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Only add valid and readyToStart info 56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) If there is no batch, create a batch and insert this transfer into batch, 56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * then run the batch 56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If there is existing batch and timestamp match, insert transfer into batch 56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 4) If there is existing batch and timestamp does not match, create a new batch and 56809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * put in queue 56909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 57109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isReadyToStart()) { 57209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 57309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* check if the file exists */ 57403f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh InputStream i; 57509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 57603f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh i = getContentResolver().openInputStream(Uri.parse(info.mUri)); 57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (FileNotFoundException e) { 57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId); 57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 58103f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh } catch (SecurityException e) { 58203f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh Log.e(TAG, "Exception:" + e.toString() + " for OUTBOUND info " + info.mId); 58303f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 58403f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh return; 58503f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh } 58603f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh 58703f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh try { 58803f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh i.close(); 58909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException ex) { 59009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "IO error when close file for OUTBOUND info " + info.mId); 59109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 59209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 59309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 59409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() == 0) { 59509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 59609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 59709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 59809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 59909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 600ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 60109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for OUTBOUND info " + info.mId); 60209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch); 60309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 604ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId 60509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for INBOUND info " + info.mId); 60609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, 60709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession); 60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 60909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 61009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND && mTransfer != null) { 611ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service start transfer new Batch " + newBatch.mId 61209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 61309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 61409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND 61509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && mServerTransfer != null) { 616ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service start server transfer new Batch " + newBatch.mId 61709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 61809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.start(); 61909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 62009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 62109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 62209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 62309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 624ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service add info " + info.mId + " to existing batch " 62509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mBatchs.get(i).mId); 62609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.get(i).addShare(info); 62709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 628888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun // There is ongoing batch 62909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 63009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 63109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 63209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 633888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (V) Log.v(TAG, "Service add new Batch " + newBatch.mId + " for info " + 634888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun info.mId); 635888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) { 636888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun // only allow concurrent serverTransfer in debug mode 637888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 638888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun if (V) Log.v(TAG, "TCP_DEBUG start server transfer new Batch " + 639888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun newBatch.mId + " for info " + info.mId); 640888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, 641888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun newBatch, mServerSession); 642888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun mServerTransfer.start(); 643888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun } 644888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun } 64509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 65009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateShare(Cursor cursor, int arrayPos, boolean userAccepted) { 6516769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 65209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS); 65309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 65409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)); 65509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mUri = stringFromCursor(info.mUri, cursor, BluetoothShare.URI); 65609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mHint = stringFromCursor(info.mHint, cursor, BluetoothShare.FILENAME_HINT); 65709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mFilename = stringFromCursor(info.mFilename, cursor, BluetoothShare._DATA); 65809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMimetype = stringFromCursor(info.mMimetype, cursor, BluetoothShare.MIMETYPE); 65909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDirection = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)); 66009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDestination = stringFromCursor(info.mDestination, cursor, BluetoothShare.DESTINATION); 66109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)); 66209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 66309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean confirmed = false; 66409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newConfirm = cursor.getInt(cursor 66509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 66609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 66709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mVisibility == BluetoothShare.VISIBILITY_VISIBLE 66809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newVisibility != BluetoothShare.VISIBILITY_VISIBLE 66909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && (BluetoothShare.isStatusCompleted(info.mStatus) || newConfirm == BluetoothShare.USER_CONFIRMATION_PENDING)) { 67009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 67109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mVisibility = newVisibility; 67409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mConfirm == BluetoothShare.USER_CONFIRMATION_PENDING 67609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newConfirm != BluetoothShare.USER_CONFIRMATION_PENDING) { 67709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly confirmed = true; 67809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mConfirm = cursor.getInt(cursor 68009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 68109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newStatus = cursor.getInt(statusColumn); 68209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 68309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!BluetoothShare.isStatusCompleted(info.mStatus) 68409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && BluetoothShare.isStatusCompleted(newStatus)) { 68509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 68609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 68709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 68809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mStatus = newStatus; 68909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)); 69009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mCurrentBytes = cursor.getInt(cursor 69109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)); 69209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTimestamp = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)); 69309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMediaScanned = (cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 69409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 69509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (confirmed) { 696ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service handle info " + info.mId + " confirmed"); 69709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Inbounds transfer get user confirmation, so we start it */ 698df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun int i = findBatchWithTimeStamp(info.mTimestamp); 6999d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (i != -1) { 7009d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothOppBatch batch = mBatchs.get(i); 7019d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (mServerTransfer != null && batch.mId == mServerTransfer.getBatchId()) { 7029d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.setConfirmed(); 7039d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } //TODO need to think about else 7049d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 70509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 70609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 70709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 70809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 70909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mStatus == Constants.BATCH_STATUS_FINISHED 71009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly || batch.mStatus == Constants.BATCH_STATUS_FAILED) { 711ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Batch " + batch.mId + " is finished"); 71209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 71309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mTransfer == null) { 71409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mTransfer is null"); 71509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mTransfer.getBatchId()) { 71609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.stop(); 71709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 71809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 71909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mTransfer id " + mTransfer.getBatchId()); 72009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 7219d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mTransfer = null; 72209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 72309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mServerTransfer == null) { 72409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mServerTransfer is null"); 72509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mServerTransfer.getBatchId()) { 72609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.stop(); 72709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 72809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 72909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mServerTransfer id " 73009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mServerTransfer.getBatchId()); 73109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 7329d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer = null; 73309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 73509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 73909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 74009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Removes the local copy of the info about a share. 74109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 74209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void deleteShare(int arrayPos) { 7436769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 74409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 74509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 74609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Delete arrayPos from a batch. The logic is 74709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Search existing batch for the info 74809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) cancel the batch 74909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If the batch become empty delete the batch 75009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 75109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 75209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 75309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 75409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.hasShare(info)) { 755ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service cancel batch for share " + info.mId); 75609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly batch.cancelBatch(); 75709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 75809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.isEmpty()) { 759ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Service remove batch " + batch.mId); 76009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 76109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.remove(arrayPos); 76409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 76609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private String stringFromCursor(String old, Cursor cursor, String column) { 76709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int index = cursor.getColumnIndexOrThrow(column); 76809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (old == null) { 76909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 77009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mNewChars == null) { 77209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNewChars = new CharArrayBuffer(128); 77309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.copyStringToBuffer(index, mNewChars); 77509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int length = mNewChars.sizeCopied; 77609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (length != old.length()) { 77709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 77809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mOldChars == null || mOldChars.sizeCopied < length) { 78009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mOldChars = new CharArrayBuffer(length); 78109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 78209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] oldArray = mOldChars.data; 78309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] newArray = mNewChars.data; 78409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly old.getChars(0, length, oldArray, 0); 78509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = length - 1; i >= 0; --i) { 78609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (oldArray[i] != newArray[i]) { 78709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return new String(newArray, 0, length); 78809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 78909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return old; 79109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 79309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int findBatchWithTimeStamp(long timestamp) { 79409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = mBatchs.size() - 1; i >= 0; i--) { 79509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.get(i).mTimestamp == timestamp) { 79609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return i; 79709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return -1; 80009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 80209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void removeBatch(BluetoothOppBatch batch) { 803ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Remove batch " + batch.mId); 80409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.remove(batch); 8059d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothOppBatch nextBatch; 80609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() > 0) { 80709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = 0; i < mBatchs.size(); i++) { 80809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // we have a running batch 8099d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun nextBatch = mBatchs.get(i); 8109d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.mStatus == Constants.BATCH_STATUS_RUNNING) { 81109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 81209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 8131ac5507790a87810061a19dadec36eb328a222eaTao Liejun // just finish a transfer, start pending outbound transfer 8149d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 8159d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "Start pending outbound batch " + nextBatch.mId); 8169d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch); 81709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 81809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 8199d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } else if (nextBatch.mDirection == BluetoothShare.DIRECTION_INBOUND 8209d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun && mServerSession != null) { 8219d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun // have to support pending inbound transfer 8229d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun // if an outbound transfer and incoming socket happens together 8239d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "Start pending inbound batch " + nextBatch.mId); 8249d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch, 8259d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerSession); 8269d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.start(); 8279d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (nextBatch.getPendingShare().mConfirm == 8289d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun BluetoothShare.USER_CONFIRMATION_CONFIRMED) { 8299d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mServerTransfer.setConfirmed(); 8309d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 8319d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun return; 83209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 83709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 83809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean needAction(int arrayPos) { 8396769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 84009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (BluetoothShare.isStatusCompleted(info.mStatus)) { 84109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return false; 84209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 84309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return true; 84409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 84509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 84609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean visibleNotification(int arrayPos) { 8476769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 84809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return info.hasCompletionNotification(); 84909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 85109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean scanFile(Cursor cursor, int arrayPos) { 8526769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 8536769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 854ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Scanning file " + info.mFilename); 8551ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (!mMediaScanInProgress) { 8561ac5507790a87810061a19dadec36eb328a222eaTao Liejun mMediaScanInProgress = true; 8571ac5507790a87810061a19dadec36eb328a222eaTao Liejun new MediaScannerNotifier(this, info, mHandler); 8581ac5507790a87810061a19dadec36eb328a222eaTao Liejun return true; 8591ac5507790a87810061a19dadec36eb328a222eaTao Liejun } else { 8601ac5507790a87810061a19dadec36eb328a222eaTao Liejun return false; 8611ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 86209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 86509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean shouldScanFile(int arrayPos) { 8666769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 8671ac5507790a87810061a19dadec36eb328a222eaTao Liejun return BluetoothShare.isStatusSuccess(info.mStatus) 8681ac5507790a87810061a19dadec36eb328a222eaTao Liejun && info.mDirection == BluetoothShare.DIRECTION_INBOUND && !info.mMediaScanned; 86909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8710a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick // Run in a background thread at boot. 8720a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick private static void trimDatabase(ContentResolver contentResolver) { 873389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String INVISIBLE = BluetoothShare.VISIBILITY + "=" + 874389f6dd45f7a45b12af847a510086125777e1198Lixin Yue BluetoothShare.VISIBILITY_HIDDEN; 875389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 876389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // remove the invisible/complete/outbound shares 877389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INVISIBLE_COMPLETE_OUTBOUND = BluetoothShare.DIRECTION + "=" 878389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_OUTBOUND + " AND " + BluetoothShare.STATUS + ">=" 879389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 8800a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick int delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 881389f6dd45f7a45b12af847a510086125777e1198Lixin Yue WHERE_INVISIBLE_COMPLETE_OUTBOUND, null); 882389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (V) Log.v(TAG, "Deleted complete outbound shares, number = " + delNum); 883389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 884389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // remove the invisible/finished/inbound/failed shares 885389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED = BluetoothShare.DIRECTION + "=" 886389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + ">" 887389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 8880a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 889389f6dd45f7a45b12af847a510086125777e1198Lixin Yue WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED, null); 890389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (V) Log.v(TAG, "Deleted complete inbound failed shares, number = " + delNum); 891389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 892389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // Only keep the inbound and successful shares for LiverFolder use 893389f6dd45f7a45b12af847a510086125777e1198Lixin Yue // Keep the latest 1000 to easy db query 894389f6dd45f7a45b12af847a510086125777e1198Lixin Yue final String WHERE_INBOUND_SUCCESS = BluetoothShare.DIRECTION + "=" 895389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + "=" 896389f6dd45f7a45b12af847a510086125777e1198Lixin Yue + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE; 8970a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick Cursor cursor = contentResolver.query(BluetoothShare.CONTENT_URI, new String[] { 89809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothShare._ID 899389f6dd45f7a45b12af847a510086125777e1198Lixin Yue }, WHERE_INBOUND_SUCCESS, null, BluetoothShare._ID); // sort by id 900389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 90109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 90209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 90309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 904389f6dd45f7a45b12af847a510086125777e1198Lixin Yue 905389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int recordNum = cursor.getCount(); 906389f6dd45f7a45b12af847a510086125777e1198Lixin Yue if (recordNum > Constants.MAX_RECORDS_IN_DATABASE) { 907389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int numToDelete = recordNum - Constants.MAX_RECORDS_IN_DATABASE; 90875fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue 90975fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue if (cursor.moveToPosition(numToDelete)) { 910389f6dd45f7a45b12af847a510086125777e1198Lixin Yue int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 91175fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue long id = cursor.getLong(columnId); 9120a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick delNum = contentResolver.delete(BluetoothShare.CONTENT_URI, 91375fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue BluetoothShare._ID + " < " + id, null); 91475fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue if (V) Log.v(TAG, "Deleted old inbound success share: " + delNum); 91509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 91609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 91709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 91809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 91909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static class MediaScannerNotifier implements MediaScannerConnectionClient { 92109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private MediaScannerConnection mConnection; 92309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppShareInfo mInfo; 92509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Context mContext; 92709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mCallback; 92909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 93009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public MediaScannerNotifier(Context context, BluetoothOppShareInfo info, Handler handler) { 93109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = context; 93209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo = info; 93309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback = handler; 93409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection = new MediaScannerConnection(mContext, this); 935ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Connecting to MediaScannerConnection "); 93609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.connect(); 93709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 93809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 93909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onMediaScannerConnected() { 940ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "MediaScannerConnection onMediaScannerConnected"); 94109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype); 94209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 94309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 94409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onScanCompleted(String path, Uri uri) { 94509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 946ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 94709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection onScanCompleted"); 94809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection path is " + path); 94909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection Uri is " + uri); 95009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 95109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (uri != null) { 95209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 95309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 95409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED; 95509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 95609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = uri; 95709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 95809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 95909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 96009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 96109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED_FAILED; 96209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 96309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 96409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (Exception ex) { 96609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "!!!MediaScannerConnection exception: " + ex); 96709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } finally { 968ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "MediaScannerConnection disconnect"); 96909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.disconnect(); 97009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 97109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 97209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 97309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 974