BluetoothOppService.java revision 41ef8d494511c040451f2f887cb31c3100746b61
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.bluetooth.BluetoothDevice; 4109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.bluetooth.BluetoothError; 4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.bluetooth.BluetoothIntent; 4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.BroadcastReceiver; 4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentUris; 4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentValues; 4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context; 4709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent; 4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.IntentFilter; 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.CharArrayBuffer; 5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.ContentObserver; 5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.Cursor; 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection; 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection.MediaScannerConnectionClient; 5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri; 5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler; 5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.IBinder; 5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message; 5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.PowerManager; 5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log; 6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Process; 6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.FileNotFoundException; 6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.IOException; 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.InputStream; 6509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.util.ArrayList; 6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 686769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * Performs the background Bluetooth OPP transfer. It also starts thread to 696769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * accept incoming OPP connection. 7009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 7109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppService extends Service { 7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean userAccepted = false; 7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private class BluetoothShareContentObserver extends ContentObserver { 7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public BluetoothShareContentObserver() { 7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super(new Handler()); 8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 8309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onChange(boolean selfChange) { 8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(Constants.TAG, "Service ContentObserver received notification"); 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateFromProvider(); 8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final String TAG = "BtOpp Service"; 9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** Observer to get notified when the content observer's data changes */ 9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothShareContentObserver mObserver; 9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** Class to handle Notification Manager updates */ 9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppNotification mNotifier; 9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mPendingUpdate; 10009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private UpdateThread mUpdateThread; 10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ArrayList<BluetoothOppShareInfo> mShares; 10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ArrayList<BluetoothOppBatch> mBatchs; 10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppTransfer mTransfer; 10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppTransfer mServerTransfer; 11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mBatchId; 11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Array used when extracting strings from content provider 11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private CharArrayBuffer mOldChars; 11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Array used when extracting strings from content provider 12009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 12109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private CharArrayBuffer mNewChars; 12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12341ef8d494511c040451f2f887cb31c3100746b61Nick Pelly private BluetoothAdapter mAdapter; 12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private PowerManager mPowerManager; 12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppRfcommListener mSocketListener; 12809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mListenStarted = false; 13009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 13209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO No support for queue incoming from multiple devices. 13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Make an array list of server session to support receiving queue from 13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * multiple devices 13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppObexServerSession mServerSession; 13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public IBinder onBind(Intent arg0) { 14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly throw new UnsupportedOperationException("Cannot bind to Bluetooth OPP Service"); 14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onCreate() { 14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onCreate(); 14609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service onCreate"); 14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14941ef8d494511c040451f2f887cb31c3100746b61Nick Pelly mAdapter = (BluetoothAdapter) getSystemService(Context.BLUETOOTH_SERVICE); 15041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 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 16109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly trimDatabase(); 16209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 16309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly IntentFilter filter = new IntentFilter(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION); 16409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION); 16509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly registerReceiver(mBluetoothIntentReceiver, filter); 16609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 1676769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 16841ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter == null) { 16909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "Local BT device is not enabled"); 17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 17109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startListenerDelayed(); 17209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 17452236de777c23788df8147de15912a57e8bc36ddTao Liejun if (Constants.LOGVV) { 17552236de777c23788df8147de15912a57e8bc36ddTao Liejun BluetoothOppPreference.getInstance(this).dump(); 17652236de777c23788df8147de15912a57e8bc36ddTao Liejun } 17709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateFromProvider(); 17809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 17909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onStart(Intent intent, int startId) { 18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onStart(intent, startId); 18309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 18409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service onStart"); 18509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 18609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 18741ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter == null) { 18809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "Local BT device is not enabled"); 18909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 19009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startListenerDelayed(); 19109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateFromProvider(); 19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 19409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void startListenerDelayed() { 19709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mListenStarted) { 19841ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter.isEnabled()) { 19909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 20009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Starting RfcommListener in 9 seconds"); 20109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mHandler.sendMessageDelayed(mHandler.obtainMessage(START_LISTENER), 9000); 20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mListenStarted = true; 20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int START_LISTENER = 1; 20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int MEDIA_SCANNED = 2; 21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final int MEDIA_SCANNED_FAILED = 3; 21309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mHandler = new Handler() { 21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void handleMessage(Message msg) { 21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly switch (msg.what) { 21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case START_LISTENER: 21941ef8d494511c040451f2f887cb31c3100746b61Nick Pelly if (mAdapter.isEnabled()) { 22009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 22109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 22309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED: 22452236de777c23788df8147de15912a57e8bc36ddTao Liejun if (Constants.LOGVV) { 22552236de777c23788df8147de15912a57e8bc36ddTao Liejun Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for data uri= " 22652236de777c23788df8147de15912a57e8bc36ddTao Liejun + msg.obj.toString()); 22752236de777c23788df8147de15912a57e8bc36ddTao Liejun } 22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(Constants.MEDIA_SCANNED, Constants.MEDIA_SCANNED_SCANNED_OK); 23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.URI, msg.obj.toString()); // update 23209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.MIMETYPE, getContentResolver().getType( 23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri.parse(msg.obj.toString()))); 23409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri, updateValues, null, null); 23509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 23609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly case MEDIA_SCANNED_FAILED: 23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for MEDIA_SCANNED_FAILED"); 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues1 = new ContentValues(); 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri1 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1); 24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues1.put(Constants.MEDIA_SCANNED, 24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.MEDIA_SCANNED_SCANNED_FAILED); 24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().update(contentUri1, updateValues1, null, null); 24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 24709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 24809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 24909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void startSocketListener() { 25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "start RfcommListener"); 25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.start(mIncomingConnectionHandler); 25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 25609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "RfcommListener started"); 25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onDestroy() { 26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service onDestroy"); 26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 26509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super.onDestroy(); 26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().unregisterContentObserver(mObserver); 26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly unregisterReceiver(mBluetoothIntentReceiver); 26809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private final Handler mIncomingConnectionHandler = new Handler() { 27209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void handleMessage(Message msg) { 27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Get incoming connection"); 27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ObexTransport transport = (ObexTransport)msg.obj; 27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 27809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO need to identify in which case we can create a 27909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * serverSession, and when we will reject connection 28009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 28109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly createServerSession(transport); 28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 28509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* suppose we auto accept an incoming OPUSH connection */ 28609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void createServerSession(ObexTransport transport) { 28709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession = new BluetoothOppObexServerSession(this, transport); 28809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession.preStart(); 28909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 29009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Get ServerSession " + mServerSession.toString() 29109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for incoming connection" + transport.toString()); 29209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 29309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 29541ef8d494511c040451f2f887cb31c3100746b61Nick Pelly private void handleRemoteDisconnected(BluetoothDevice remoteDevice) { 29609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 29741ef8d494511c040451f2f887cb31c3100746b61Nick Pelly Log.v(TAG, "Handle remote device disconnected " + remoteDevice); 29809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 29909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int batchId = -1; 30009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i; 30109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mTransfer != null) { 30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly batchId = mTransfer.getBatchId(); 30309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly i = findBatchWithId(batchId); 30409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1 && mBatchs.get(i).mStatus == Constants.BATCH_STATUS_RUNNING 30541ef8d494511c040451f2f887cb31c3100746b61Nick Pelly && mBatchs.get(i).mDestination.equals(remoteDevice)) { 30609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 30741ef8d494511c040451f2f887cb31c3100746b61Nick Pelly Log.v(TAG, "Find mTransfer is running for remote device " + remoteDevice); 30809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 30909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.stop(); 31009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 31109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (mServerTransfer != null) { 31309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly batchId = mServerTransfer.getBatchId(); 31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly i = findBatchWithId(batchId); 31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1 && mBatchs.get(i).mStatus == Constants.BATCH_STATUS_RUNNING 31641ef8d494511c040451f2f887cb31c3100746b61Nick Pelly && mBatchs.get(i).mDestination.equals(remoteDevice)) { 31709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 31841ef8d494511c040451f2f887cb31c3100746b61Nick Pelly Log.v(TAG, "Find mServerTransfer is running for remote device " + remoteDevice); 31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private final BroadcastReceiver mBluetoothIntentReceiver = new BroadcastReceiver() { 32509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onReceive(Context context, Intent intent) { 32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String action = intent.getAction(); 32841ef8d494511c040451f2f887cb31c3100746b61Nick Pelly BluetoothDevice remoteDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE); 32909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (action.equals(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION)) { 33109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 33241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly Log.v(TAG, "Receiver REMOTE_DEVICE_DISCONNECTED_ACTION from " + remoteDevice); 33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 33441ef8d494511c040451f2f887cb31c3100746b61Nick Pelly handleRemoteDisconnected(remoteDevice); 33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) { 33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly switch (intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE, BluetoothError.ERROR)) { 33941ef8d494511c040451f2f887cb31c3100746b61Nick Pelly case BluetoothAdapter.BLUETOOTH_STATE_ON: 34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, 34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "Receiver BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON"); 34309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly startSocketListener(); 34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 34641ef8d494511c040451f2f887cb31c3100746b61Nick Pelly case BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF: 34709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Receiver DISABLED_ACTION "); 34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSocketListener.stop(); 35109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mListenStarted = false; 3526769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }; 36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateFromProvider() { 3646769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = true; 36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread == null) { 36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = new UpdateThread(); 36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread.start(); 36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private class UpdateThread extends Thread { 37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public UpdateThread() { 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly super("Bluetooth Share Service"); 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void run() { 38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean keepUpdateThread = false; 38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (;;) { 3846769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mUpdateThread != this) { 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly throw new IllegalStateException( 38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly "multiple UpdateThreads in BluetoothOppService"); 38809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 39009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "pendingUpdate is " + mPendingUpdate + " keepUpdateThread is " 39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + keepUpdateThread + " sListenStarted is " + mListenStarted); 39209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mPendingUpdate) { 39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mUpdateThread = null; 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!keepUpdateThread && !mListenStarted) { 39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly stopSelf(); 39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mPendingUpdate = false; 40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = getContentResolver().query(BluetoothShare.CONTENT_URI, null, null, 40409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly null, BluetoothShare._ID); 40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 40709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToFirst(); 41109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayPos = 0; 41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = false; 41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean isAfterLast = cursor.isAfterLast(); 41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int idColumn = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 41809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Walk the cursor and the local array to keep them in sync. The 42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * key to the algorithm is that the ids are unique and sorted 42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * both in the cursor and in the array, so that they can be 42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed in order in both sources at the same time: at each 42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * step, both sources point to the lowest id that hasn't been 42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * processed from that source, and the algorithm processes the 42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * lowest id from those two possibilities. At each step: -If the 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * array contains an entry that's not in the cursor, remove the 42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * entry, move to next entry in the array. -If the array 42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's in the cursor, nothing to do, move 42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * to next cursor row and next array entry. -If the cursor 43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * contains an entry that's not in the array, insert a new entry 43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * in the array, move to next cursor row and next array entry. 43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (!isAfterLast || arrayPos < mShares.size()) { 43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (isAfterLast) { 43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // We're beyond the end of the cursor but there's still 43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // some 43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // stuff in the local array, which can only be junk 43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 4396769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun int arrayId = mShares.get(arrayPos).mId; 44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Array update: trimming " + arrayId + " @ " + arrayPos); 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); // this advances in the array 44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int id = cursor.getInt(idColumn); 44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayPos == mShares.size()) { 45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Array update: inserting " + id + " @ " + arrayPos); 45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int arrayId = mShares.get(arrayPos).mId; 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (arrayId < id) { 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Array update: removing " + arrayId + " @ " 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + arrayPos); 47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos)) { 47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly scanFile(null, arrayPos); 47809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly deleteShare(arrayPos); 48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (arrayId == id) { 48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor row already exists in the stored 48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateShare(cursor, arrayPos, userAccepted); 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 49109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This cursor entry didn't exist in the stored 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // array 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Array update: appending " + id + " @ " + arrayPos); 50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly insertShare(cursor, arrayPos); 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) { 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (visibleNotification(arrayPos)) { 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needAction(arrayPos)) { 51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly keepUpdateThread = true; 51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ++arrayPos; 51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.moveToNext(); 51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly isAfterLast = cursor.isAfterLast(); 51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.updateNotification(); 52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void insertShare(Cursor cursor, int arrayPos) { 53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppShareInfo info = new BluetoothOppShareInfo( 53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)), 53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.URI)), 53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT)), 53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare._DATA)), 53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.MIMETYPE)), 53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)), 53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION)), 53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)), 54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)), 54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)), 54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)), 54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)), 54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)), 54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 54609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service adding new entry"); 54909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "ID : " + info.mId); 55009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // Log.v(TAG, "URI : " + ((info.mUri != null) ? "yes" : "no")); 55109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "URI : " + info.mUri); 55209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "HINT : " + info.mHint); 55309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "FILENAME: " + info.mFilename); 55409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MIMETYPE: " + info.mMimetype); 55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DIRECTION: " + info.mDirection); 55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DESTINAT: " + info.mDestination); 55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "VISIBILI: " + info.mVisibility); 55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CONFIRM : " + info.mConfirm); 55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "STATUS : " + info.mStatus); 56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TOTAL : " + info.mTotalBytes); 56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "CURRENT : " + info.mCurrentBytes); 56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TIMESTAMP : " + info.mTimestamp); 56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "SCANNED : " + info.mMediaScanned); 56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.add(arrayPos, info); 56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 56809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Mark the info as failed if it's in invalid status */ 56909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isObsolete()) { 57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_UNKNOWN_ERROR); 57109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 57209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 57309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Add info into a batch. The logic is 57409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Only add valid and readyToStart info 57509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) If there is no batch, create a batch and insert this transfer into batch, 57609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * then run the batch 57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If there is existing batch and timestamp match, insert transfer into batch 57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 4) If there is existing batch and timestamp does not match, create a new batch and 57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * put in queue 58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 58109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 58209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.isReadyToStart()) { 58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* check if the file exists */ 58509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 58609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly InputStream i = getContentResolver().openInputStream(Uri.parse(info.mUri)); 58709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly i.close(); 58809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (FileNotFoundException e) { 58909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId); 59009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST); 59109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 59209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException ex) { 59309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "IO error when close file for OUTBOUND info " + info.mId); 59409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 59509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 59609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 59709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() == 0) { 59809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 59909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 60009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 60109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 60209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 60309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 60409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service create new Batch " + newBatch.mId 60509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for OUTBOUND info " + info.mId); 60609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 60709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch); 60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) { 60909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 61009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service create new Batch " + newBatch.mId 61109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for INBOUND info " + info.mId); 61209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 61309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, 61409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerSession); 61509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 61609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 61709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND && mTransfer != null) { 61809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 61909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service start transfer new Batch " + newBatch.mId 62009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 62109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 62209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 62309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND 62409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && mServerTransfer != null) { 62509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 62609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO investigate here later? 62709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 62809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 62909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service start server transfer new Batch " + newBatch.mId 63009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " for info " + info.mId); 63109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 63209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.start(); 63309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 63409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 63509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 63609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 63709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 63809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 63909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service add info " + info.mId + " to existing batch " 64009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mBatchs.get(i).mId); 64109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 64209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.get(i).addShare(info); 64309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 64409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info); 64509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly newBatch.mId = mBatchId; 64609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchId++; 64709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.add(newBatch); 64809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 64909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service add new Batch " + newBatch.mId + " for info " 65009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + info.mId); 65109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 65209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 65309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 65409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 65509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 65609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 65709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void updateShare(Cursor cursor, int arrayPos, boolean userAccepted) { 6586769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 65909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS); 66009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 66109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)); 66209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mUri = stringFromCursor(info.mUri, cursor, BluetoothShare.URI); 66309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mHint = stringFromCursor(info.mHint, cursor, BluetoothShare.FILENAME_HINT); 66409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mFilename = stringFromCursor(info.mFilename, cursor, BluetoothShare._DATA); 66509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMimetype = stringFromCursor(info.mMimetype, cursor, BluetoothShare.MIMETYPE); 66609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDirection = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)); 66709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mDestination = stringFromCursor(info.mDestination, cursor, BluetoothShare.DESTINATION); 66809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)); 66909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean confirmed = false; 67109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newConfirm = cursor.getInt(cursor 67209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 67309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 67409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mVisibility == BluetoothShare.VISIBILITY_VISIBLE 67509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newVisibility != BluetoothShare.VISIBILITY_VISIBLE 67609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && (BluetoothShare.isStatusCompleted(info.mStatus) || newConfirm == BluetoothShare.USER_CONFIRMATION_PENDING)) { 67709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 67809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 67909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 68009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mVisibility = newVisibility; 68109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 68209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (info.mConfirm == BluetoothShare.USER_CONFIRMATION_PENDING 68309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && newConfirm != BluetoothShare.USER_CONFIRMATION_PENDING) { 68409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly confirmed = true; 68509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 68609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mConfirm = cursor.getInt(cursor 68709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)); 68809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int newStatus = cursor.getInt(statusColumn); 68909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 69009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!BluetoothShare.isStatusCompleted(info.mStatus) 69109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && BluetoothShare.isStatusCompleted(newStatus)) { 69209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNotifier.mNotificationMgr.cancel(info.mId); 69309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 69409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 69509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mStatus = newStatus; 69609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)); 69709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mCurrentBytes = cursor.getInt(cursor 69809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)); 69909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mTimestamp = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)); 70009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly info.mMediaScanned = (cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED); 70109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 70209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (confirmed) { 70309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 70409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service handle info " + info.mId + " confirmed"); 70509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 70609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Inbounds transfer get user confirmation, so we start it */ 707df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun int i = findBatchWithTimeStamp(info.mTimestamp); 708df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun BluetoothOppBatch batch = mBatchs.get(i); 709df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun if (batch.mId == mServerTransfer.getBatchId()) { 710df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun mServerTransfer.setConfirmed(); 711df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun } //TODO need to think about else 71209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 71309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 71409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 71509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 71609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mStatus == Constants.BATCH_STATUS_FINISHED 71709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly || batch.mStatus == Constants.BATCH_STATUS_FAILED) { 71809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 71909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Batch " + batch.mId + " is finished"); 72009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 72109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) { 72209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mTransfer == null) { 72309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mTransfer is null"); 72409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mTransfer.getBatchId()) { 72509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.stop(); 72609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 72709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 72809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mTransfer id " + mTransfer.getBatchId()); 72909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 73009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 73109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mServerTransfer == null) { 73209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! mServerTransfer is null"); 73309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (batch.mId == mServerTransfer.getBatchId()) { 73409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerTransfer.stop(); 73509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 73609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error! batch id " + batch.mId 73709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + " doesn't match mServerTransfer id " 73809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mServerTransfer.getBatchId()); 73909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 74009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 74109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 74209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 74309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 74409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 74509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 74609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 74709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Removes the local copy of the info about a share. 74809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 74909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void deleteShare(int arrayPos) { 7506769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 75109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 75209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 75309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Delete arrayPos from a batch. The logic is 75409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1) Search existing batch for the info 75509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2) cancel the batch 75609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 3) If the batch become empty delete the batch 75709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 75809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int i = findBatchWithTimeStamp(info.mTimestamp); 75909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (i != -1) { 76009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppBatch batch = mBatchs.get(i); 76109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.hasShare(info)) { 76209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 76309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service cancel batch for share " + info.mId); 76409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly batch.cancelBatch(); 76609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 76709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.isEmpty()) { 76809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 76909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service remove batch " + batch.mId); 77009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly removeBatch(batch); 77209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mShares.remove(arrayPos); 77509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 77609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 77709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private String stringFromCursor(String old, Cursor cursor, String column) { 77809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int index = cursor.getColumnIndexOrThrow(column); 77909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (old == null) { 78009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 78109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 78209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mNewChars == null) { 78309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mNewChars = new CharArrayBuffer(128); 78409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 78509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.copyStringToBuffer(index, mNewChars); 78609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int length = mNewChars.sizeCopied; 78709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (length != old.length()) { 78809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return cursor.getString(index); 78909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mOldChars == null || mOldChars.sizeCopied < length) { 79109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mOldChars = new CharArrayBuffer(length); 79209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 79309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] oldArray = mOldChars.data; 79409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly char[] newArray = mNewChars.data; 79509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly old.getChars(0, length, oldArray, 0); 79609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = length - 1; i >= 0; --i) { 79709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (oldArray[i] != newArray[i]) { 79809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return new String(newArray, 0, length); 79909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return old; 80209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 80409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int findBatchWithTimeStamp(long timestamp) { 80509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = mBatchs.size() - 1; i >= 0; i--) { 80609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.get(i).mTimestamp == timestamp) { 80709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return i; 80809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 80909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return -1; 81109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 81309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int findBatchWithId(int id) { 81409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 81509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Service search batch for id " + id + " from " + mBatchs.size()); 81609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 81709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = mBatchs.size() - 1; i >= 0; i--) { 81809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.get(i).mId == id) { 81909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return i; 82009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return -1; 82309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 82509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void removeBatch(BluetoothOppBatch batch) { 82609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 82709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Remove batch " + batch.mId); 82809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 82909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mBatchs.remove(batch); 83009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.size() > 0) { 83109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly for (int i = 0; i < mBatchs.size(); i++) { 83209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // we have a running batch 83309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mBatchs.get(i).mStatus == Constants.BATCH_STATUS_RUNNING) { 83409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 83509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 83609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 83709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO Pending batch for inbound transfer is not considered 83809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * here 83909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 84009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // we have a pending batch 84109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (batch.mDirection == mBatchs.get(i).mDirection) { 84209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 84309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Start pending batch " + mBatchs.get(i).mId); 84409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 84509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer = new BluetoothOppTransfer(this, mPowerManager, mBatchs.get(i)); 84609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransfer.start(); 84709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 84809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 84909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 85409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean needAction(int arrayPos) { 8556769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 85609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (BluetoothShare.isStatusCompleted(info.mStatus)) { 85709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return false; 85809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 85909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return true; 86009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 86209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean visibleNotification(int arrayPos) { 8636769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 86409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return info.hasCompletionNotification(); 86509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 86609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 86709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean scanFile(Cursor cursor, int arrayPos) { 8686769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 8696769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun synchronized (BluetoothOppService.this) { 87009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 87109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Scanning file " + info.mFilename); 87209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly new MediaScannerNotifier(this, info, mHandler); 87409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return true; 87509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 87709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 87809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean shouldScanFile(int arrayPos) { 8796769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun BluetoothOppShareInfo info = mShares.get(arrayPos); 88009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return !info.mMediaScanned && info.mDirection == BluetoothShare.DIRECTION_INBOUND 88109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && BluetoothShare.isStatusSuccess(info.mStatus); 88209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 88309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 88409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 88509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void trimDatabase() { 88609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Cursor cursor = getContentResolver().query(BluetoothShare.CONTENT_URI, new String[] { 88709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothShare._ID 88809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly }, BluetoothShare.STATUS + " >= '200'", null, BluetoothShare._ID); 88909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor == null) { 89009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // This isn't good - if we can't do basic queries in our database, 89109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // nothing's gonna work 89209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "null cursor in trimDatabase"); 89309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return; 89409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 89509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (cursor.moveToFirst()) { 89609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int numDelete = cursor.getCount() - Constants.MAX_RECORDS_IN_DATABASE; 89709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID); 89809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (numDelete > 0) { 89909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly getContentResolver().delete( 90009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentUris.withAppendedId(BluetoothShare.CONTENT_URI, cursor 90109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .getLong(columnId)), null, null); 90209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!cursor.moveToNext()) { 90309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 90409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 90509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly numDelete--; 90609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 90709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 90809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly cursor.close(); 90909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 91009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 91109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static class MediaScannerNotifier implements MediaScannerConnectionClient { 91209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 91309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private MediaScannerConnection mConnection; 91409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 91509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppShareInfo mInfo; 91609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 91709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Context mContext; 91809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 91909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mCallback; 92009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 92109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public MediaScannerNotifier(Context context, BluetoothOppShareInfo info, Handler handler) { 92209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = context; 92309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo = info; 92409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback = handler; 92509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection = new MediaScannerConnection(mContext, this); 92609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 92709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Connecting to MediaScannerConnection "); 92809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 92909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.connect(); 93009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 93109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 93209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onMediaScannerConnected() { 93309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 93409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection onMediaScannerConnected"); 93509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 93609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype); 93709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 93809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 93909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onScanCompleted(String path, Uri uri) { 94009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 94109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 94209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection onScanCompleted"); 94309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection path is " + path); 94409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection Uri is " + uri); 94509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 94609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (uri != null) { 94709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 94809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 94909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED; 95009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 95109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = uri; 95209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 95309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 95409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(); 95509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.setTarget(mCallback); 95609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = MEDIA_SCANNED_FAILED; 95709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.arg1 = mInfo.mId; 95809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 95909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (Exception ex) { 96109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "!!!MediaScannerConnection exception: " + ex); 96209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } finally { 96309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 96409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MediaScannerConnection disconnect"); 96509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mConnection.disconnect(); 96709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 96909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 97009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 971