1 /* 2 * Copyright (c) 2008-2009, Motorola, Inc. 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Motorola, Inc. nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.android.bluetooth.opp; 34 35 import android.bluetooth.BluetoothAdapter; 36 import android.bluetooth.BluetoothDevice; 37 import android.content.Context; 38 import android.util.Log; 39 40 import java.util.ArrayList; 41 42 /** 43 * This class stores information about a batch of OPP shares that should be 44 * transferred in one session. 45 */ 46 /*There are a few cases: 1. create a batch for a single file to send 47 * 2. create a batch for multiple files to send 48 * 3. add additional file(s) to existing batch to send 49 * 4. create a batch for receive single file 50 * 5. add additional file to existing batch to receive (this only happens as the server 51 * session notify more files to receive) 52 * 6. Cancel sending a single file 53 * 7. Cancel sending a file from multiple files (implies cancel the transfer, rest of 54 * the unsent files are also canceled) 55 * 8. Cancel receiving a single file 56 * 9. Cancel receiving a file (implies cancel the transfer, no additional files will be received) 57 */ 58 59 public class BluetoothOppBatch { 60 private static final String TAG = "BtOppBatch"; 61 private static final boolean V = Constants.VERBOSE; 62 63 public int mId; 64 public int mStatus; 65 66 public final long mTimestamp; 67 public final int mDirection; 68 public final BluetoothDevice mDestination; 69 70 private BluetoothOppBatchListener mListener; 71 72 private final ArrayList<BluetoothOppShareInfo> mShares; 73 private final Context mContext; 74 75 /** 76 * An interface for notifying when BluetoothOppTransferBatch is changed 77 */ 78 public interface BluetoothOppBatchListener { 79 /** 80 * Called to notify when a share is added into the batch 81 * @param id , BluetoothOppShareInfo.id 82 */ onShareAdded(int id)83 void onShareAdded(int id); 84 85 /** 86 * Called to notify when a share is deleted from the batch 87 * @param id , BluetoothOppShareInfo.id 88 */ onShareDeleted(int id)89 void onShareDeleted(int id); 90 91 /** 92 * Called to notify when the batch is canceled 93 */ onBatchCanceled()94 void onBatchCanceled(); 95 } 96 97 /** 98 * A batch is always created with at least one ShareInfo 99 * @param context, Context 100 * @param info, BluetoothOppShareInfo 101 */ BluetoothOppBatch(Context context, BluetoothOppShareInfo info)102 public BluetoothOppBatch(Context context, BluetoothOppShareInfo info) { 103 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 104 mContext = context; 105 mShares = new ArrayList(); 106 mTimestamp = info.mTimestamp; 107 mDirection = info.mDirection; 108 mDestination = adapter.getRemoteDevice(info.mDestination); 109 mStatus = Constants.BATCH_STATUS_PENDING; 110 mShares.add(info); 111 112 if (V) { 113 Log.v(TAG, "New Batch created for info " + info.mId); 114 } 115 } 116 117 /** 118 * Add one share into the batch. 119 */ 120 /* There are 2 cases: Service scans the databases and it's multiple send 121 * Service receives database update and know additional file should be received 122 */ addShare(BluetoothOppShareInfo info)123 public void addShare(BluetoothOppShareInfo info) { 124 mShares.add(info); 125 if (mListener != null) { 126 mListener.onShareAdded(info.mId); 127 } 128 } 129 130 /** 131 * Cancel the whole batch. 132 */ 133 /* 1) If the batch is running, stop the transfer 134 * 2) Go through mShares list and mark all incomplete share as CANCELED status 135 * 3) update ContentProvider for these canceled transfer 136 */ cancelBatch()137 public void cancelBatch() { 138 if (V) { 139 Log.v(TAG, "batch " + this.mId + " is canceled"); 140 } 141 142 if (mListener != null) { 143 mListener.onBatchCanceled(); 144 } 145 //TODO investigate if below code is redundant 146 for (int i = mShares.size() - 1; i >= 0; i--) { 147 BluetoothOppShareInfo info = mShares.get(i); 148 149 if (info.mStatus < 200) { 150 if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mUri != null) { 151 mContext.getContentResolver().delete(info.mUri, null, null); 152 } 153 if (V) { 154 Log.v(TAG, "Cancel batch for info " + info.mId); 155 } 156 157 Constants.updateShareStatus(mContext, info.mId, BluetoothShare.STATUS_CANCELED); 158 } 159 } 160 mShares.clear(); 161 } 162 163 /** check if a specific share is in this batch */ hasShare(BluetoothOppShareInfo info)164 public boolean hasShare(BluetoothOppShareInfo info) { 165 return mShares.contains(info); 166 } 167 168 /** if this batch is empty */ isEmpty()169 public boolean isEmpty() { 170 return (mShares.size() == 0); 171 } 172 getNumShares()173 public int getNumShares() { 174 return mShares.size(); 175 } 176 177 /** 178 * Get the running status of the batch 179 * @return 180 */ 181 182 /** register a listener for the batch change */ registerListern(BluetoothOppBatchListener listener)183 public void registerListern(BluetoothOppBatchListener listener) { 184 mListener = listener; 185 } 186 187 /** 188 * Get the first pending ShareInfo of the batch 189 * @return BluetoothOppShareInfo, for the first pending share, or null if 190 * none exists 191 */ getPendingShare()192 public BluetoothOppShareInfo getPendingShare() { 193 for (int i = 0; i < mShares.size(); i++) { 194 BluetoothOppShareInfo share = mShares.get(i); 195 if (share.mStatus == BluetoothShare.STATUS_PENDING) { 196 return share; 197 } 198 } 199 return null; 200 } 201 } 202