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