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