HandoverTransfer.java revision 116dfa0107cdc7ab098ed95828280542bf6b0a1e
1be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectpackage com.android.nfc.handover;
2be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
3be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.app.Notification;
4be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.app.NotificationManager;
5be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.app.PendingIntent;
6be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.app.Notification.Builder;
7be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.bluetooth.BluetoothDevice;
8be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.content.ContentResolver;
9be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.content.Context;
10be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.content.Intent;
11be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.media.MediaScannerConnection;
12be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.net.Uri;
13be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.Environment;
14be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.Handler;
15be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.Looper;
16be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.Message;
17be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.SystemClock;
18be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.os.UserHandle;
19be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport android.util.Log;
20be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
21be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport com.android.nfc.R;
22be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
23be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport java.io.File;
24be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport java.text.SimpleDateFormat;
25be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport java.util.ArrayList;
26be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport java.util.Date;
27be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectimport java.util.HashMap;
28116dfa0107cdc7ab098ed95828280542bf6b0a1eThe Android Open Source Projectimport java.util.Locale;
29be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
30be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project/**
31be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * A HandoverTransfer object represents a set of files
32be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * that were received through NFC connection handover
33be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * from the same source address.
34be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project *
35be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * For Bluetooth, files are received through OPP, and
36be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * we have no knowledge how many files will be transferred
37be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * as part of a single transaction.
38be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * Hence, a transfer has a notion of being "alive": if
39be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * the last update to a transfer was within WAIT_FOR_NEXT_TRANSFER_MS
40be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * milliseconds, we consider a new file transfer from the
41be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * same source address as part of the same transfer.
42be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project * The corresponding URIs will be grouped in a single folder.
43be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project *
44be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project */
45be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Projectpublic class HandoverTransfer implements Handler.Callback,
46be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        MediaScannerConnection.OnScanCompletedListener {
47be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
48be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    interface Callback {
49be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        void onTransferComplete(HandoverTransfer transfer, boolean success);
50be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    };
51be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
52be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final String TAG = "HandoverTransfer";
53be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
54be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final Boolean DBG = true;
55be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
56be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // In the states below we still accept new file transfer
57be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_NEW = 0;
58be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_IN_PROGRESS = 1;
59be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_W4_NEXT_TRANSFER = 2;
60be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
61be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // In the states below no new files are accepted.
62be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_W4_MEDIA_SCANNER = 3;
63be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_FAILED = 4;
64be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_SUCCESS = 5;
65be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int STATE_CANCELLED = 6;
66be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
67be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int MSG_NEXT_TRANSFER_TIMER = 0;
68be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int MSG_TRANSFER_TIMEOUT = 1;
69be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
70be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // We need to receive an update within this time period
71be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // to still consider this transfer to be "alive" (ie
72be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // a reason to keep the handover transport enabled).
73be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int ALIVE_CHECK_MS = 20000;
74be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
75be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // The amount of time to wait for a new transfer
76be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // once the current one completes.
77be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final int WAIT_FOR_NEXT_TRANSFER_MS = 4000;
78be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
79be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    static final String BEAM_DIR = "beam";
80be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
81be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final boolean mIncoming;  // whether this is an incoming transfer
82be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final int mTransferId; // Unique ID of this transfer used for notifications
83be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final PendingIntent mCancelIntent;
84be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final Context mContext;
85be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final Handler mHandler;
86be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final NotificationManager mNotificationManager;
87be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final BluetoothDevice mRemoteDevice;
88be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    final Callback mCallback;
89be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
90be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    // Variables below are only accessed on the main thread
91be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    int mState;
92be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    boolean mCalledBack;
93be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    Long mLastUpdate; // Last time an event occurred for this transfer
94be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    float mProgress; // Progress in range [0..1]
95be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    ArrayList<Uri> mBtUris; // Received uris from Bluetooth OPP
96be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    ArrayList<String> mBtMimeTypes; // Mime-types received from Bluetooth OPP
97be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
98be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    ArrayList<String> mPaths; // Raw paths on the filesystem for Beam-stored files
99be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    HashMap<String, String> mMimeTypes; // Mime-types associated with each path
100be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    HashMap<String, Uri> mMediaUris; // URIs found by the media scanner for each path
101be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    int mUrisScanned;
102be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
103be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public HandoverTransfer(Context context, Callback callback,
104be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            PendingHandoverTransfer pendingTransfer) {
105be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mContext = context;
106be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mCallback = callback;
107be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mRemoteDevice = pendingTransfer.remoteDevice;
108be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mIncoming = pendingTransfer.incoming;
109be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mTransferId = pendingTransfer.id;
110be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mLastUpdate = SystemClock.elapsedRealtime();
111be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mProgress = 0.0f;
112be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mState = STATE_NEW;
113be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mBtUris = new ArrayList<Uri>();
114be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mBtMimeTypes = new ArrayList<String>();
115be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mPaths = new ArrayList<String>();
116be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mMimeTypes = new HashMap<String, String>();
117be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mMediaUris = new HashMap<String, Uri>();
118be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mCancelIntent = buildCancelIntent();
119be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mUrisScanned = 0;
120be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
121be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mHandler = new Handler(Looper.getMainLooper(), this);
122be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mHandler.sendEmptyMessageDelayed(MSG_TRANSFER_TIMEOUT, ALIVE_CHECK_MS);
123be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mNotificationManager = (NotificationManager) mContext.getSystemService(
124be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                Context.NOTIFICATION_SERVICE);
125be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
126be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
127be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    void whitelistOppDevice(BluetoothDevice device) {
128be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (DBG) Log.d(TAG, "Whitelisting " + device + " for BT OPP");
129be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Intent intent = new Intent(HandoverManager.ACTION_WHITELIST_DEVICE);
130be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
131be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
132be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
133be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
134be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public void updateFileProgress(float progress) {
135be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (!isRunning()) return; // Ignore when we're no longer running
136be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
137be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mHandler.removeMessages(MSG_NEXT_TRANSFER_TIMER);
138be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
139be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        this.mProgress = progress;
140be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
141be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // We're still receiving data from this device - keep it in
142be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // the whitelist for a while longer
143be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mIncoming) whitelistOppDevice(mRemoteDevice);
144be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
145be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        updateStateAndNotification(STATE_IN_PROGRESS);
146be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
147be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
148be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public void finishTransfer(boolean success, Uri uri, String mimeType) {
149be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (!isRunning()) return; // Ignore when we're no longer running
150be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
151be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (success && uri != null) {
152be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (DBG) Log.d(TAG, "Transfer success, uri " + uri + " mimeType " + mimeType);
153be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            this.mProgress = 1.0f;
154be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (mimeType == null) {
155be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mimeType = BluetoothOppHandover.getMimeTypeForUri(mContext, uri);
156be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
157be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (mimeType != null) {
158be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mBtUris.add(uri);
159be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mBtMimeTypes.add(mimeType);
160be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            } else {
161be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                if (DBG) Log.d(TAG, "Could not get mimeType for file.");
162be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
163be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
164be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Log.e(TAG, "Handover transfer failed");
165be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // Do wait to see if there's another file coming.
166be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
167be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mHandler.removeMessages(MSG_NEXT_TRANSFER_TIMER);
168be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mHandler.sendEmptyMessageDelayed(MSG_NEXT_TRANSFER_TIMER, WAIT_FOR_NEXT_TRANSFER_MS);
169be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        updateStateAndNotification(STATE_W4_NEXT_TRANSFER);
170be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
171be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
172be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public boolean isRunning() {
173be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mState != STATE_NEW && mState != STATE_IN_PROGRESS && mState != STATE_W4_NEXT_TRANSFER) {
174be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return false;
175be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
176be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return true;
177be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
178be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
179be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
180be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    void cancel() {
181be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (!isRunning()) return;
182be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
183be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // Delete all files received so far
184be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        for (Uri uri : mBtUris) {
185be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            File file = new File(uri.getPath());
186be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (file.exists()) file.delete();
187be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
188be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
189be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        updateStateAndNotification(STATE_CANCELLED);
190be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
191be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
192be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    void updateNotification() {
193be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (!mIncoming) return; // No notifications for outgoing transfers
194be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
195be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Builder notBuilder = new Notification.Builder(mContext);
196be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
197be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mState == STATE_NEW || mState == STATE_IN_PROGRESS ||
198be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mState == STATE_W4_NEXT_TRANSFER || mState == STATE_W4_MEDIA_SCANNER) {
199be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setAutoCancel(false);
200be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setSmallIcon(android.R.drawable.stat_sys_download);
201be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setTicker(mContext.getString(R.string.beam_progress));
202be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentTitle(mContext.getString(R.string.beam_progress));
203be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.addAction(R.drawable.ic_menu_cancel_holo_dark,
204be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                    mContext.getString(R.string.cancel), mCancelIntent);
205be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setDeleteIntent(mCancelIntent);
206be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // We do have progress indication on a per-file basis, but in a multi-file
207be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // transfer we don't know the total progress. So for now, just show an
208be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // indeterminate progress bar.
209be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setProgress(100, 0, true);
210be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else if (mState == STATE_SUCCESS) {
211be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setAutoCancel(true);
212be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done);
213be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setTicker(mContext.getString(R.string.beam_complete));
214be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentTitle(mContext.getString(R.string.beam_complete));
215be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view));
216be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
217be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Intent viewIntent = buildViewIntent();
218be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            PendingIntent contentIntent = PendingIntent.getActivity(
219be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                    mContext, 0, viewIntent, 0, null);
220be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
221be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentIntent(contentIntent);
222be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else if (mState == STATE_FAILED) {
223be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setAutoCancel(false);
224be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done);
225be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setTicker(mContext.getString(R.string.beam_failed));
226be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentTitle(mContext.getString(R.string.beam_failed));
227be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else if (mState == STATE_CANCELLED) {
228be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setAutoCancel(false);
229be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done);
230be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setTicker(mContext.getString(R.string.beam_canceled));
231be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            notBuilder.setContentTitle(mContext.getString(R.string.beam_canceled));
232be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
233be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return;
234be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
235be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
236be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mNotificationManager.notify(null, mTransferId, notBuilder.build());
237be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
238be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
239be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    void updateStateAndNotification(int newState) {
240be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        this.mState = newState;
241be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        this.mLastUpdate = SystemClock.elapsedRealtime();
242be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
243be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mHandler.hasMessages(MSG_TRANSFER_TIMEOUT)) {
244be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // Update timeout timer
245be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            mHandler.removeMessages(MSG_TRANSFER_TIMEOUT);
246be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            mHandler.sendEmptyMessageDelayed(MSG_TRANSFER_TIMEOUT, ALIVE_CHECK_MS);
247be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
248be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
249be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        updateNotification();
250be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
251be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if ((mState == STATE_SUCCESS || mState == STATE_FAILED || mState == STATE_CANCELLED)
252be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                && !mCalledBack) {
253be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            mCalledBack = true;
254be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // Notify that we're done with this transfer
255be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            mCallback.onTransferComplete(this, mState == STATE_SUCCESS);
256be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
257be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
258be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
259be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    void processFiles() {
260be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // Check the amount of files we received in this transfer;
261be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // If more than one, create a separate directory for it.
262be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String extRoot = Environment.getExternalStorageDirectory().getPath();
263be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        File beamPath = new File(extRoot + "/" + BEAM_DIR);
264be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
265be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (!checkMediaStorage(beamPath) || mBtUris.size() == 0) {
266be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Log.e(TAG, "Media storage not valid or no uris received.");
267be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            updateStateAndNotification(STATE_FAILED);
268be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return;
269be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
270be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
271be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mBtUris.size() > 1) {
272be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            beamPath = generateMultiplePath(extRoot + "/" + BEAM_DIR + "/");
273be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (!beamPath.isDirectory() && !beamPath.mkdir()) {
274be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                Log.e(TAG, "Failed to create multiple path " + beamPath.toString());
275be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                updateStateAndNotification(STATE_FAILED);
276be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                return;
277be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
278be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
279be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
280be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        for (int i = 0; i < mBtUris.size(); i++) {
281be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Uri uri = mBtUris.get(i);
282be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            String mimeType = mBtMimeTypes.get(i);
283be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
284be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            File srcFile = new File(uri.getPath());
285be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
286be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            File dstFile = generateUniqueDestination(beamPath.getAbsolutePath(),
287be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                    uri.getLastPathSegment());
288be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (!srcFile.renameTo(dstFile)) {
289be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                if (DBG) Log.d(TAG, "Failed to rename from " + srcFile + " to " + dstFile);
290be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                srcFile.delete();
291be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                return;
292be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            } else {
293be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mPaths.add(dstFile.getAbsolutePath());
294be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mMimeTypes.put(dstFile.getAbsolutePath(), mimeType);
295be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                if (DBG) Log.d(TAG, "Did successful rename from " + srcFile + " to " + dstFile);
296be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
297be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
298be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
299be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // We can either add files to the media provider, or provide an ACTION_VIEW
300be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // intent to the file directly. We base this decision on the mime type
301be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // of the first file; if it's media the platform can deal with,
302be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // use the media provider, if it's something else, just launch an ACTION_VIEW
303be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // on the file.
304be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String mimeType = mMimeTypes.get(mPaths.get(0));
305be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mimeType.startsWith("image/") || mimeType.startsWith("video/") ||
306be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                mimeType.startsWith("audio/")) {
307be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            String[] arrayPaths = new String[mPaths.size()];
308be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            MediaScannerConnection.scanFile(mContext, mPaths.toArray(arrayPaths), null, this);
309be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            updateStateAndNotification(STATE_W4_MEDIA_SCANNER);
310be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
311be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // We're done.
312be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            updateStateAndNotification(STATE_SUCCESS);
313be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
314be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
315be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
316be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
317be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public int getTransferId() {
318be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return mTransferId;
319be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
320be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
321be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public boolean handleMessage(Message msg) {
322be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (msg.what == MSG_NEXT_TRANSFER_TIMER) {
323be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // We didn't receive a new transfer in time, finalize this one
324be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (mIncoming) {
325be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                processFiles();
326be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            } else {
327be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                updateStateAndNotification(STATE_SUCCESS);
328be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
329be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return true;
330be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else if (msg.what == MSG_TRANSFER_TIMEOUT) {
331be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // No update on this transfer for a while, check
332be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // to see if it's still running, and fail it if it is.
333be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (isRunning()) {
334be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                updateStateAndNotification(STATE_FAILED);
335be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
336be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
337be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return false;
338be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
339be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
340be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    public synchronized void onScanCompleted(String path, Uri uri) {
341be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (DBG) Log.d(TAG, "Scan completed, path " + path + " uri " + uri);
342be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (uri != null) {
343be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            mMediaUris.put(path, uri);
344be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
345be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        mUrisScanned++;
346be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mUrisScanned == mPaths.size()) {
347be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            // We're done
348be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            updateStateAndNotification(STATE_SUCCESS);
349be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
350be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
351be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
352be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    boolean checkMediaStorage(File path) {
353be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
354be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            if (!path.isDirectory() && !path.mkdir()) {
355be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                Log.e(TAG, "Not dir or not mkdir " + path.getAbsolutePath());
356be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                return false;
357be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            }
358be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return true;
359be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
360be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Log.e(TAG, "External storage not mounted, can't store file.");
361be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            return false;
362be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
363be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
364be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
365be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    Intent buildViewIntent() {
366be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (mPaths.size() == 0) return null;
367be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
368be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Intent viewIntent = new Intent(Intent.ACTION_VIEW);
369be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
370be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String filePath = mPaths.get(0);
371be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Uri mediaUri = mMediaUris.get(filePath);
372be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Uri uri =  mediaUri != null ? mediaUri :
373be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            Uri.parse(ContentResolver.SCHEME_FILE + "://" + filePath);
374be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        viewIntent.setDataAndTypeAndNormalize(uri, mMimeTypes.get(filePath));
375be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
376be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return viewIntent;
377be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
378be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
379be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    PendingIntent buildCancelIntent() {
380be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        Intent intent = new Intent(HandoverService.ACTION_CANCEL_HANDOVER_TRANSFER);
381be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        intent.putExtra(HandoverService.EXTRA_SOURCE_ADDRESS, mRemoteDevice.getAddress());
382be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
383be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
384be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return pi;
385be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
386be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
387be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    File generateUniqueDestination(String path, String fileName) {
388be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        int dotIndex = fileName.lastIndexOf(".");
389be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String extension = null;
390be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String fileNameWithoutExtension = null;
391be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        if (dotIndex < 0) {
392be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            extension = "";
393be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            fileNameWithoutExtension = fileName;
394be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        } else {
395be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            extension = fileName.substring(dotIndex);
396be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            fileNameWithoutExtension = fileName.substring(0, dotIndex);
397be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
398be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        File dstFile = new File(path + File.separator + fileName);
399be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        int count = 0;
400be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        while (dstFile.exists()) {
401be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            dstFile = new File(path + File.separator + fileNameWithoutExtension + "-" +
402be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                    Integer.toString(count) + extension);
403be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            count++;
404be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
405be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return dstFile;
406be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
407be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
408be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    File generateMultiplePath(String beamRoot) {
409be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        // Generate a unique directory with the date
410be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String format = "yyyy-MM-dd";
411116dfa0107cdc7ab098ed95828280542bf6b0a1eThe Android Open Source Project        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
412be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        String newPath = beamRoot + "beam-" + sdf.format(new Date());
413be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        File newFile = new File(newPath);
414be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        int count = 0;
415be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        while (newFile.exists()) {
416be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            newPath = beamRoot + "beam-" + sdf.format(new Date()) + "-" +
417be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project                    Integer.toString(count);
418be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            newFile = new File(newPath);
419be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project            count++;
420be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        }
421be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project        return newFile;
422be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project    }
423be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project}
424be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project
425