BluetoothOppBatch.java revision ce4d93666275df294cb073fe41de5b85932570a8
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
33package com.android.bluetooth.opp;
34
35import java.io.File;
36import java.util.ArrayList;
37
38import android.bluetooth.BluetoothAdapter;
39import android.bluetooth.BluetoothDevice;
40import android.content.Context;
41import android.util.Log;
42
43import com.google.android.collect.Lists;
44
45/**
46 * This class stores information about a batch of OPP shares that should be
47 * transferred in one session.
48 */
49/*There are a few cases: 1. create a batch for a single file to send
50 * 2. create a batch for multiple files to send
51 * 3. add additional file(s) to existing batch to send
52 * 4. create a batch for receive single file
53 * 5. add additional file to existing batch to receive (this only happens as the server
54 * session notify more files to receive)
55 * 6. Cancel sending a single file
56 * 7. Cancel sending a file from multiple files (implies cancel the transfer, rest of
57 * the unsent files are also canceled)
58 * 8. Cancel receiving a single file
59 * 9. Cancel receiving a file (implies cancel the transfer, no additional files will be received)
60 */
61
62public class BluetoothOppBatch {
63    private static final String TAG = "BtOppBatch";
64    private static final boolean D = Constants.DEBUG;
65    private static final boolean V = Constants.VERBOSE;
66
67    public int mId;
68    public int mStatus;
69
70    public final long mTimestamp;
71    public final int mDirection;
72    public final BluetoothDevice mDestination;
73
74    private BluetoothOppBatchListener mListener;
75
76    private final ArrayList<BluetoothOppShareInfo> mShares;
77    private final Context mContext;
78
79    /**
80     * An interface for notifying when BluetoothOppTransferBatch is changed
81     */
82    public interface BluetoothOppBatchListener {
83        /**
84         * Called to notify when a share is added into the batch
85         * @param id , BluetoothOppShareInfo.id
86         */
87        public void onShareAdded(int id);
88
89        /**
90         * Called to notify when a share is deleted from the batch
91         * @param id , BluetoothOppShareInfo.id
92         */
93        public void onShareDeleted(int id);
94
95        /**
96         * Called to notify when the batch is canceled
97         */
98        public void onBatchCanceled();
99    }
100
101    /**
102     * A batch is always created with at least one ShareInfo
103     * @param context, Context
104     * @param info, BluetoothOppShareInfo
105     */
106    public BluetoothOppBatch(Context context, BluetoothOppShareInfo info) {
107        BluetoothAdapter adapter =
108                (BluetoothAdapter) context.getSystemService(Context.BLUETOOTH_SERVICE);
109        mContext = context;
110        mShares = Lists.newArrayList();
111        mTimestamp = info.mTimestamp;
112        mDirection = info.mDirection;
113        mDestination = adapter.getRemoteDevice(info.mDestination);
114        mStatus = Constants.BATCH_STATUS_PENDING;
115        mShares.add(info);
116
117        if (V) Log.v(TAG, "New Batch created for info " + info.mId);
118    }
119
120    /**
121     * Add one share into the batch.
122     */
123    /* There are 2 cases: Service scans the databases and it's multiple send
124     * Service receives database update and know additional file should be received
125     */
126
127    public void addShare(BluetoothOppShareInfo info) {
128        mShares.add(info);
129        if (mListener != null) {
130            mListener.onShareAdded(info.mId);
131        }
132    }
133
134    /**
135     * Delete one share from the batch.
136     */
137    /*It should only be called under requirement that cancel one single share, but not to
138     * cancel the whole batch. Currently we assume "cancel" is to cancel whole batch.
139     */
140    //TODO: consider if the batch is running or not
141    public void deleteShare(BluetoothOppShareInfo info) {
142        if (info.mStatus == BluetoothShare.STATUS_RUNNING) {
143            info.mStatus = BluetoothShare.STATUS_CANCELED;
144            if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mFilename != null) {
145                new File(info.mFilename).delete();
146            }
147        }
148
149        if (mListener != null) {
150            mListener.onShareDeleted(info.mId);
151        }
152    }
153
154    /**
155     * Cancel the whole batch.
156     */
157    /* 1) If the batch is running, stop the transfer
158     * 2) Go through mShares list and mark all incomplete share as CANCELED status
159     * 3) update ContentProvider for these canceled transfer
160     */
161    public void cancelBatch() {
162        if (V) Log.v(TAG, "batch " + this.mId + " is canceled");
163
164        if (mListener != null) {
165            mListener.onBatchCanceled();
166        }
167        //TODO investigate if below code is redundant
168        for (int i = mShares.size() - 1; i >= 0; i--) {
169            BluetoothOppShareInfo info = mShares.get(i);
170
171            if (info.mStatus < 200) {
172                if (info.mDirection == BluetoothShare.DIRECTION_INBOUND && info.mFilename != null) {
173                    new File(info.mFilename).delete();
174                }
175                if (V) Log.v(TAG, "Cancel batch for info " + info.mId);
176
177                Constants.updateShareStatus(mContext, info.mId, BluetoothShare.STATUS_CANCELED);
178            }
179        }
180        mShares.clear();
181    }
182
183    /** check if a specific share is in this batch */
184    public boolean hasShare(BluetoothOppShareInfo info) {
185        return mShares.contains(info);
186    }
187
188    /** if this batch is empty */
189    public boolean isEmpty() {
190        return (mShares.size() == 0);
191    }
192
193    /**
194     * Get the running status of the batch
195     * @return
196     */
197    public boolean isRunning() {
198        return (mStatus == Constants.BATCH_STATUS_RUNNING);
199    }
200
201    /** register a listener for the batch change */
202    public void registerListern(BluetoothOppBatchListener listener) {
203        mListener = listener;
204    }
205
206    /**
207     * Get the first pending ShareInfo of the batch
208     * @return BluetoothOppShareInfo, for the first pending share, or null if
209     *         none exists
210     */
211    public BluetoothOppShareInfo getPendingShare() {
212        for (int i = 0; i < mShares.size(); i++) {
213            BluetoothOppShareInfo share = mShares.get(i);
214            if (share.mStatus == BluetoothShare.STATUS_PENDING) {
215                return share;
216            }
217        }
218        return null;
219    }
220}
221