BluetoothOppService.java revision 3fafe61ef25c1899fdc817c52163aec16c31055c
109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/*
209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * All rights reserved.
509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Redistribution and use in source and binary forms, with or without
709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * modification, are permitted provided that the following conditions are met:
809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions of source code must retain the above copyright notice,
1009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer.
1109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
1209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
1309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer in the documentation
1409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * and/or other materials provided with the distribution.
1509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
1609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
1709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * may be used to endorse or promote products derived from this software
1809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * without specific prior written permission.
1909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly *
2009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
3109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */
3209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypackage com.android.bluetooth.opp;
3409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport com.google.android.collect.Lists;
3609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ObexTransport;
3709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.app.Service;
3941ef8d494511c040451f2f887cb31c3100746b61Nick Pellyimport android.bluetooth.BluetoothAdapter;
4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.BroadcastReceiver;
410a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrickimport android.content.ContentResolver;
4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentValues;
4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context;
4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent;
4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.IntentFilter;
4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.CharArrayBuffer;
4709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.ContentObserver;
4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.database.Cursor;
4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection;
5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.media.MediaScannerConnection.MediaScannerConnectionClient;
5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri;
5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler;
5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.IBinder;
5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message;
5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.PowerManager;
5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log;
5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Process;
5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.FileNotFoundException;
6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.IOException;
6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.InputStream;
6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.util.ArrayList;
6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/**
656769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * Performs the background Bluetooth OPP transfer. It also starts thread to
666769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * accept incoming OPP connection.
6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */
6809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppService extends Service {
70ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final boolean D = Constants.DEBUG;
71ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final boolean V = Constants.VERBOSE;
7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean userAccepted = false;
7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private class BluetoothShareContentObserver extends ContentObserver {
7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public BluetoothShareContentObserver() {
7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            super(new Handler());
7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        @Override
8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void onChange(boolean selfChange) {
83ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (V) Log.v(TAG, "ContentObserver received notification");
8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            updateFromProvider();
8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static final String TAG = "BtOpp Service";
8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /** Observer to get notified when the content observer's data changes */
9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothShareContentObserver mObserver;
9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /** Class to handle Notification Manager updates */
9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppNotification mNotifier;
9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean mPendingUpdate;
9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private UpdateThread mUpdateThread;
9909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private ArrayList<BluetoothOppShareInfo> mShares;
10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private ArrayList<BluetoothOppBatch> mBatchs;
10309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppTransfer mTransfer;
10509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppTransfer mServerTransfer;
10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int mBatchId;
10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Array used when extracting strings from content provider
11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private CharArrayBuffer mOldChars;
11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Array used when extracting strings from content provider
11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private CharArrayBuffer mNewChars;
11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
12041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly    private BluetoothAdapter mAdapter;
12109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private PowerManager mPowerManager;
12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppRfcommListener mSocketListener;
12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean mListenStarted = false;
12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
1281ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private boolean mMediaScanInProgress;
1291ac5507790a87810061a19dadec36eb328a222eaTao Liejun
1301ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private int mIncomingRetries = 0;
1311ac5507790a87810061a19dadec36eb328a222eaTao Liejun
1321ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private ObexTransport mPendingConnection = null;
1331ac5507790a87810061a19dadec36eb328a222eaTao Liejun
13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /*
13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * TODO No support for queue incoming from multiple devices.
13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Make an array list of server session to support receiving queue from
13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * multiple devices
13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppObexServerSession mServerSession;
14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public IBinder onBind(Intent arg0) {
14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        throw new UnsupportedOperationException("Cannot bind to Bluetooth OPP Service");
14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
14609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void onCreate() {
14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        super.onCreate();
149ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "Service onCreate");
1503a88b20fcd71e42451e402d27374b19eeb2ff0daNick Pelly        mAdapter = BluetoothAdapter.getDefaultAdapter();
15141ef8d494511c040451f2f887cb31c3100746b61Nick Pelly        mSocketListener = new BluetoothOppRfcommListener(mAdapter);
15209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mShares = Lists.newArrayList();
15309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mBatchs = Lists.newArrayList();
15409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mObserver = new BluetoothShareContentObserver();
15509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver);
15609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mBatchId = 1;
15709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotifier = new BluetoothOppNotification(this);
15809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotifier.mNotificationMgr.cancelAll();
15909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mNotifier.updateNotification();
16009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
1610a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        final ContentResolver contentResolver = getContentResolver();
1620a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        new Thread("trimDatabase") {
1630a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick            public void run() {
1640a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick                trimDatabase(contentResolver);
1650a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick            }
1660a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        }.start();
16709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
168f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
169f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly        registerReceiver(mBluetoothReceiver, filter);
17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
1716769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        synchronized (BluetoothOppService.this) {
17241ef8d494511c040451f2f887cb31c3100746b61Nick Pelly            if (mAdapter == null) {
17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.w(TAG, "Local BT device is not enabled");
17409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
175ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim                startListener();
17609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
17709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
178ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) BluetoothOppPreference.getInstance(this).dump();
17909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        updateFromProvider();
18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
1838222c7902a2281929fd31e840f6012038e6fa44aLixin Yue    public int onStartCommand(Intent intent, int flags, int startId) {
1848222c7902a2281929fd31e840f6012038e6fa44aLixin Yue        if (V) Log.v(TAG, "Service onStartCommand");
1858222c7902a2281929fd31e840f6012038e6fa44aLixin Yue        int retCode = super.onStartCommand(intent, flags, startId);
1868222c7902a2281929fd31e840f6012038e6fa44aLixin Yue        if (retCode == START_STICKY) {
1878222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            if (mAdapter == null) {
1888222c7902a2281929fd31e840f6012038e6fa44aLixin Yue                Log.w(TAG, "Local BT device is not enabled");
1898222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            } else {
190ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim                startListener();
1918222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            }
1928222c7902a2281929fd31e840f6012038e6fa44aLixin Yue            updateFromProvider();
19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
1948222c7902a2281929fd31e840f6012038e6fa44aLixin Yue        return retCode;
19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
197ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim    private void startListener() {
19809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!mListenStarted) {
19941ef8d494511c040451f2f887cb31c3100746b61Nick Pelly            if (mAdapter.isEnabled()) {
200ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim                if (V) Log.v(TAG, "Starting RfcommListener");
201ef697b0b9a74e15b5003e134307e72b20b48de12jhtop.kim                mHandler.sendMessage(mHandler.obtainMessage(START_LISTENER));
20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mListenStarted = true;
20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static final int START_LISTENER = 1;
20809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static final int MEDIA_SCANNED = 2;
21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static final int MEDIA_SCANNED_FAILED = 3;
21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
2131ac5507790a87810061a19dadec36eb328a222eaTao Liejun    private static final int MSG_INCOMING_CONNECTION_RETRY = 4;
2141ac5507790a87810061a19dadec36eb328a222eaTao Liejun
21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private Handler mHandler = new Handler() {
21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        @Override
21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void handleMessage(Message msg) {
21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            switch (msg.what) {
21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                case START_LISTENER:
22041ef8d494511c040451f2f887cb31c3100746b61Nick Pelly                    if (mAdapter.isEnabled()) {
22109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        startSocketListener();
22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
22309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    break;
22409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                case MEDIA_SCANNED:
225ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for data uri= "
22652236de777c23788df8147de15912a57e8bc36ddTao Liejun                                + msg.obj.toString());
22709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    ContentValues updateValues = new ContentValues();
22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1);
22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues.put(Constants.MEDIA_SCANNED, Constants.MEDIA_SCANNED_SCANNED_OK);
23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues.put(BluetoothShare.URI, msg.obj.toString()); // update
23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues.put(BluetoothShare.MIMETYPE, getContentResolver().getType(
23209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            Uri.parse(msg.obj.toString())));
23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    getContentResolver().update(contentUri, updateValues, null, null);
2341ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    synchronized (BluetoothOppService.this) {
2351ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mMediaScanInProgress = false;
2361ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    }
23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    break;
23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                case MEDIA_SCANNED_FAILED:
23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.v(TAG, "Update mInfo.id " + msg.arg1 + " for MEDIA_SCANNED_FAILED");
24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    ContentValues updateValues1 = new ContentValues();
24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Uri contentUri1 = Uri.parse(BluetoothShare.CONTENT_URI + "/" + msg.arg1);
24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues1.put(Constants.MEDIA_SCANNED,
24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            Constants.MEDIA_SCANNED_SCANNED_FAILED);
24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    getContentResolver().update(contentUri1, updateValues1, null, null);
2451ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    synchronized (BluetoothOppService.this) {
2461ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mMediaScanInProgress = false;
2471ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    }
2481ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    break;
2491ac5507790a87810061a19dadec36eb328a222eaTao Liejun                case BluetoothOppRfcommListener.MSG_INCOMING_BTOPP_CONNECTION:
250ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (D) Log.d(TAG, "Get incoming connection");
2511ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    ObexTransport transport = (ObexTransport)msg.obj;
2521ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    /*
2531ac5507790a87810061a19dadec36eb328a222eaTao Liejun                     * Strategy for incoming connections:
2541ac5507790a87810061a19dadec36eb328a222eaTao Liejun                     * 1. If there is no ongoing transfer, no on-hold connection, start it
2551ac5507790a87810061a19dadec36eb328a222eaTao Liejun                     * 2. If there is ongoing transfer, hold it for 20 seconds(1 seconds * 20 times)
2561ac5507790a87810061a19dadec36eb328a222eaTao Liejun                     * 3. If there is on-hold connection, reject directly
2571ac5507790a87810061a19dadec36eb328a222eaTao Liejun                     */
2581ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    if (mBatchs.size() == 0 && mPendingConnection == null) {
2591ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        Log.i(TAG, "Start Obex Server");
2601ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        createServerSession(transport);
2611ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    } else {
2621ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        if (mPendingConnection != null) {
2631ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Log.w(TAG, "OPP busy! Reject connection");
2641ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            try {
2651ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                transport.close();
2661ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            } catch (IOException e) {
2671ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                Log.e(TAG, "close tranport error");
2681ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            }
269a930b6831d0c70b6c5d34e548e6b1dceaa6529a0Mohammad Shamsi                        } else if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) {
270888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            Log.i(TAG, "Start Obex Server in TCP DEBUG mode");
271888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            createServerSession(transport);
2721ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        } else {
2731ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Log.i(TAG, "OPP busy! Retry after 1 second");
2741ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mIncomingRetries = mIncomingRetries + 1;
2751ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mPendingConnection = transport;
2761ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Message msg1 = Message.obtain(mHandler);
2771ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            msg1.what = MSG_INCOMING_CONNECTION_RETRY;
2781ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mHandler.sendMessageDelayed(msg1, 1000);
2791ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        }
2801ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    }
2811ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    break;
2821ac5507790a87810061a19dadec36eb328a222eaTao Liejun                case MSG_INCOMING_CONNECTION_RETRY:
2831ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    if (mBatchs.size() == 0) {
2841ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        Log.i(TAG, "Start Obex Server");
2851ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        createServerSession(mPendingConnection);
2861ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mIncomingRetries = 0;
2871ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mPendingConnection = null;
2881ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    } else {
2891ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        if (mIncomingRetries == 20) {
2901ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Log.w(TAG, "Retried 20 seconds, reject connection");
2911ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            try {
2921ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                mPendingConnection.close();
2931ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            } catch (IOException e) {
2941ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                Log.e(TAG, "close tranport error");
2951ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            }
2961ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mIncomingRetries = 0;
2971ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mPendingConnection = null;
2981ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        } else {
2991ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Log.i(TAG, "OPP busy! Retry after 1 second");
3001ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mIncomingRetries = mIncomingRetries + 1;
3011ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            Message msg2 = Message.obtain(mHandler);
3021ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            msg2.what = MSG_INCOMING_CONNECTION_RETRY;
3031ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            mHandler.sendMessageDelayed(msg2, 1000);
3041ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        }
3051ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    }
3061ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    break;
30709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
30809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
30909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    };
31009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
31109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void startSocketListener() {
31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
313ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "start RfcommListener");
3141ac5507790a87810061a19dadec36eb328a222eaTao Liejun        mSocketListener.start(mHandler);
315ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "RfcommListener started");
31609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
31709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void onDestroy() {
320ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "Service onDestroy");
32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        super.onDestroy();
32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        getContentResolver().unregisterContentObserver(mObserver);
323f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly        unregisterReceiver(mBluetoothReceiver);
32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mSocketListener.stop();
3253fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        _cleanup();
3263fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan    }
3273fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan
3283fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan    /* Cleanup all local references. Called during onDestroy */
3293fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan    private void _cleanup() {
3303fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mBatchs != null) {
3313fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mBatchs.clear();
3323fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mBatchs = null;
3333fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3343fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mShares != null) {
3353fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mShares.clear();
3363fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mShares = null;
3373fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3383fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mObserver != null)
3393fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mObserver = null;
3403fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mNotifier != null)
3413fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mNotifier = null;
3423fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mHandler != null) {
3433fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mHandler.removeCallbacksAndMessages(null);
3443fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mHandler = null;
3453fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3463fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mSocketListener != null)
3473fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mSocketListener = null;
3483fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mPowerManager != null)
3493fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mPowerManager = null;
3503fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mPendingConnection != null)
3513fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mPendingConnection = null;
3523fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mTransfer != null) {
3533fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mTransfer.cleanup();
3543fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mTransfer = null;
3553fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3563fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mServerTransfer!= null) {
3573fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mServerTransfer.cleanup();
3583fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mServerTransfer = null;
3593fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        }
3603fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan        if(mAdapter != null)
3613fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan            mAdapter = null;
36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /* suppose we auto accept an incoming OPUSH connection */
36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void createServerSession(ObexTransport transport) {
36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mServerSession = new BluetoothOppObexServerSession(this, transport);
36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mServerSession.preStart();
368ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "Get ServerSession " + mServerSession.toString()
36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    + " for incoming connection" + transport.toString());
37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
372f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly    private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        @Override
37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void onReceive(Context context, Intent intent) {
37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            String action = intent.getAction();
37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
377f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
378613bae227d65f61903e196944a9c718b4394f25aNick Pelly                switch (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
379f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly                    case BluetoothAdapter.STATE_ON:
380ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (V) Log.v(TAG,
38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                    "Receiver BLUETOOTH_STATE_CHANGED_ACTION, BLUETOOTH_STATE_ON");
38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        startSocketListener();
38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        break;
384f4a286ee2aba5a75abe41881334bbdb5d0080105Nick Pelly                    case BluetoothAdapter.STATE_TURNING_OFF:
385ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (V) Log.v(TAG, "Receiver DISABLED_ACTION ");
38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mSocketListener.stop();
38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mListenStarted = false;
3886769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun                        synchronized (BluetoothOppService.this) {
38909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            if (mUpdateThread == null) {
39009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                stopSelf();
39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            }
39209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        }
39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        break;
39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    };
39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void updateFromProvider() {
4006769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        synchronized (BluetoothOppService.this) {
40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mPendingUpdate = true;
40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mUpdateThread == null) {
40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mUpdateThread = new UpdateThread();
40409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mUpdateThread.start();
40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
40709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
40909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private class UpdateThread extends Thread {
41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public UpdateThread() {
41109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            super("Bluetooth Share Service");
41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
41409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        @Override
41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void run() {
41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
4181ac5507790a87810061a19dadec36eb328a222eaTao Liejun            boolean keepService = false;
41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            for (;;) {
4206769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun                synchronized (BluetoothOppService.this) {
42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (mUpdateThread != this) {
42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        throw new IllegalStateException(
42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                "multiple UpdateThreads in BluetoothOppService");
42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
425ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "pendingUpdate is " + mPendingUpdate + " keepUpdateThread is "
4261ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                + keepService + " sListenStarted is " + mListenStarted);
42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (!mPendingUpdate) {
42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mUpdateThread = null;
4291ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        if (!keepService && !mListenStarted) {
43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            stopSelf();
43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            break;
43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        }
43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        return;
43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mPendingUpdate = false;
43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Cursor cursor = getContentResolver().query(BluetoothShare.CONTENT_URI, null, null,
43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        null, BluetoothShare._ID);
43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (cursor == null) {
44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    return;
44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.moveToFirst();
44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                int arrayPos = 0;
44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
4481ac5507790a87810061a19dadec36eb328a222eaTao Liejun                keepService = false;
44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                boolean isAfterLast = cursor.isAfterLast();
45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                int idColumn = cursor.getColumnIndexOrThrow(BluetoothShare._ID);
45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /*
45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * Walk the cursor and the local array to keep them in sync. The
45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * key to the algorithm is that the ids are unique and sorted
45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * both in the cursor and in the array, so that they can be
45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * processed in order in both sources at the same time: at each
45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * step, both sources point to the lowest id that hasn't been
45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * processed from that source, and the algorithm processes the
45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * lowest id from those two possibilities. At each step: -If the
46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * array contains an entry that's not in the cursor, remove the
46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * entry, move to next entry in the array. -If the array
46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * contains an entry that's in the cursor, nothing to do, move
46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * to next cursor row and next array entry. -If the cursor
46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * contains an entry that's not in the array, insert a new entry
46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * in the array, move to next cursor row and next array entry.
46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 */
46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while (!isAfterLast || arrayPos < mShares.size()) {
46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (isAfterLast) {
46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        // We're beyond the end of the cursor but there's still
47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        // some
47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        // stuff in the local array, which can only be junk
47203f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                        if (V) Log.v(TAG, "Array update: trimming " +
473ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                                mShares.get(arrayPos).mId + " @ " + arrayPos);
47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        if (shouldScanFile(arrayPos)) {
47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            scanFile(null, arrayPos);
47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        }
47809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        deleteShare(arrayPos); // this advances in the array
47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else {
48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        int id = cursor.getInt(idColumn);
48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        if (arrayPos == mShares.size()) {
48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            insertShare(cursor, arrayPos);
484ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                            if (V) Log.v(TAG, "Array update: inserting " + id + " @ " + arrayPos);
48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) {
4861ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                keepService = true;
48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            }
48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            if (visibleNotification(arrayPos)) {
4891ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                keepService = true;
49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            }
49109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            if (needAction(arrayPos)) {
4921ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                keepService = true;
49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            }
49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            ++arrayPos;
49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            cursor.moveToNext();
49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            isAfterLast = cursor.isAfterLast();
49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        } else {
49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            int arrayId = mShares.get(arrayPos).mId;
50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            if (arrayId < id) {
502ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                                if (V) Log.v(TAG, "Array update: removing " + arrayId + " @ "
50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                            + arrayPos);
50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (shouldScanFile(arrayPos)) {
50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                    scanFile(null, arrayPos);
50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                deleteShare(arrayPos);
50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            } else if (arrayId == id) {
50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                // This cursor row already exists in the stored
51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                // array
51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                updateShare(cursor, arrayPos, userAccepted);
51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) {
5131ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (visibleNotification(arrayPos)) {
5161ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (needAction(arrayPos)) {
5191ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                ++arrayPos;
52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                cursor.moveToNext();
52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                isAfterLast = cursor.isAfterLast();
52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            } else {
52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                // This cursor entry didn't exist in the stored
52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                // array
528ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                                if (V) Log.v(TAG, "Array update: appending " + id + " @ " + arrayPos);
52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                insertShare(cursor, arrayPos);
53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (shouldScanFile(arrayPos) && (!scanFile(cursor, arrayPos))) {
5321ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (visibleNotification(arrayPos)) {
5351ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                if (needAction(arrayPos)) {
5381ac5507790a87810061a19dadec36eb328a222eaTao Liejun                                    keepService = true;
53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                }
54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                ++arrayPos;
54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                cursor.moveToNext();
54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                isAfterLast = cursor.isAfterLast();
54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            }
54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        }
54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
54609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mNotifier.updateNotification();
54909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
55009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.close();
55109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
55209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
55309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
55409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void insertShare(Cursor cursor, int arrayPos) {
55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BluetoothOppShareInfo info = new BluetoothOppShareInfo(
55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID)),
55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.URI)),
56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.FILENAME_HINT)),
56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare._DATA)),
56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.MIMETYPE)),
56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION)),
56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getString(cursor.getColumnIndexOrThrow(BluetoothShare.DESTINATION)),
56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY)),
56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION)),
56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.STATUS)),
56809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES)),
56909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES)),
57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP)),
57109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED);
57209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
573ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) {
57409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "Service adding new entry");
57509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "ID      : " + info.mId);
57609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            // Log.v(TAG, "URI     : " + ((info.mUri != null) ? "yes" : "no"));
57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "URI     : " + info.mUri);
57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "HINT    : " + info.mHint);
57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "FILENAME: " + info.mFilename);
58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "MIMETYPE: " + info.mMimetype);
58109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "DIRECTION: " + info.mDirection);
58209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "DESTINAT: " + info.mDestination);
58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "VISIBILI: " + info.mVisibility);
58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "CONFIRM : " + info.mConfirm);
58509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "STATUS  : " + info.mStatus);
58609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "TOTAL   : " + info.mTotalBytes);
58709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "CURRENT : " + info.mCurrentBytes);
58809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "TIMESTAMP : " + info.mTimestamp);
58909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "SCANNED : " + info.mMediaScanned);
59009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
59109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
59209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mShares.add(arrayPos, info);
59309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
59409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /* Mark the info as failed if it's in invalid status */
59509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (info.isObsolete()) {
59609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_UNKNOWN_ERROR);
59709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
59809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
59909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * Add info into a batch. The logic is
60009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 1) Only add valid and readyToStart info
60109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 2) If there is no batch, create a batch and insert this transfer into batch,
60209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * then run the batch
60309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 3) If there is existing batch and timestamp match, insert transfer into batch
60409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 4) If there is existing batch and timestamp does not match, create a new batch and
60509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * put in queue
60609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
60709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (info.isReadyToStart()) {
60909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
61009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /* check if the file exists */
61103f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                InputStream i;
61209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                try {
61303f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                    i = getContentResolver().openInputStream(Uri.parse(info.mUri));
61409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } catch (FileNotFoundException e) {
61509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId);
61609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST);
61709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    return;
61803f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                } catch (SecurityException e) {
61903f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                    Log.e(TAG, "Exception:" + e.toString() + " for OUTBOUND info " + info.mId);
62003f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                    Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST);
62103f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                    return;
62203f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                }
62303f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh
62403f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                try {
62503f598bafa0fc0cbde0c5ab8fed89e07a67d482eJaikumar Ganesh                    i.close();
62609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } catch (IOException ex) {
62709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.e(TAG, "IO error when close file for OUTBOUND info " + info.mId);
62809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    return;
62909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
63009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
63109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mBatchs.size() == 0) {
63209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info);
63309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                newBatch.mId = mBatchId;
63409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mBatchId++;
63509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mBatchs.add(newBatch);
63609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
637ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId
63809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " for OUTBOUND info " + info.mId);
63909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch);
64009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) {
641ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Service create new Batch " + newBatch.mId
64209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " for INBOUND info " + info.mId);
64309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch,
64409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            mServerSession);
64509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
64609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
64709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (info.mDirection == BluetoothShare.DIRECTION_OUTBOUND && mTransfer != null) {
648ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Service start transfer new Batch " + newBatch.mId
64909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " for info " + info.mId);
65009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mTransfer.start();
65109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else if (info.mDirection == BluetoothShare.DIRECTION_INBOUND
65209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        && mServerTransfer != null) {
653ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Service start server transfer new Batch " + newBatch.mId
65409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " for info " + info.mId);
65509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mServerTransfer.start();
65609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
65709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
65809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
65909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                int i = findBatchWithTimeStamp(info.mTimestamp);
66009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (i != -1) {
661ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Service add info " + info.mId + " to existing batch "
66209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + mBatchs.get(i).mId);
66309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mBatchs.get(i).addShare(info);
66409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
665888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                    // There is ongoing batch
66609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    BluetoothOppBatch newBatch = new BluetoothOppBatch(this, info);
66709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    newBatch.mId = mBatchId;
66809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mBatchId++;
66909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mBatchs.add(newBatch);
670888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                    if (V) Log.v(TAG, "Service add new Batch " + newBatch.mId + " for info " +
671888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            info.mId);
672888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                    if (Constants.USE_TCP_DEBUG && !Constants.USE_TCP_SIMPLE_SERVER) {
673888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                        // only allow  concurrent serverTransfer in debug mode
674888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                        if (info.mDirection == BluetoothShare.DIRECTION_INBOUND) {
675888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            if (V) Log.v(TAG, "TCP_DEBUG start server transfer new Batch " +
676888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                                    newBatch.mId + " for info " + info.mId);
677888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            mServerTransfer = new BluetoothOppTransfer(this, mPowerManager,
678888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                                    newBatch, mServerSession);
679888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                            mServerTransfer.start();
680888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                        }
681888485a3f5fe991116c5536bb6d6903d47b63a70Tao Liejun                    }
68209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
68309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
68409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
68509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
68609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
68709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void updateShare(Cursor cursor, int arrayPos, boolean userAccepted) {
6886769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
68909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int statusColumn = cursor.getColumnIndexOrThrow(BluetoothShare.STATUS);
69009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
69109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mId = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare._ID));
69209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mUri = stringFromCursor(info.mUri, cursor, BluetoothShare.URI);
69309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mHint = stringFromCursor(info.mHint, cursor, BluetoothShare.FILENAME_HINT);
69409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mFilename = stringFromCursor(info.mFilename, cursor, BluetoothShare._DATA);
69509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mMimetype = stringFromCursor(info.mMimetype, cursor, BluetoothShare.MIMETYPE);
69609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mDirection = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.DIRECTION));
69709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mDestination = stringFromCursor(info.mDestination, cursor, BluetoothShare.DESTINATION);
69809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int newVisibility = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.VISIBILITY));
69909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
70009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        boolean confirmed = false;
70109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int newConfirm = cursor.getInt(cursor
70209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION));
70309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
70409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (info.mVisibility == BluetoothShare.VISIBILITY_VISIBLE
70509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                && newVisibility != BluetoothShare.VISIBILITY_VISIBLE
70609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                && (BluetoothShare.isStatusCompleted(info.mStatus) || newConfirm == BluetoothShare.USER_CONFIRMATION_PENDING)) {
70709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mNotifier.mNotificationMgr.cancel(info.mId);
70809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
70909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
71009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mVisibility = newVisibility;
71109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
71209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (info.mConfirm == BluetoothShare.USER_CONFIRMATION_PENDING
71309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                && newConfirm != BluetoothShare.USER_CONFIRMATION_PENDING) {
71409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            confirmed = true;
71509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
71609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mConfirm = cursor.getInt(cursor
71709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                .getColumnIndexOrThrow(BluetoothShare.USER_CONFIRMATION));
71809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int newStatus = cursor.getInt(statusColumn);
71909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
72009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!BluetoothShare.isStatusCompleted(info.mStatus)
72109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                && BluetoothShare.isStatusCompleted(newStatus)) {
72209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mNotifier.mNotificationMgr.cancel(info.mId);
72309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
72409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
72509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mStatus = newStatus;
72609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mTotalBytes = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TOTAL_BYTES));
72709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mCurrentBytes = cursor.getInt(cursor
72809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                .getColumnIndexOrThrow(BluetoothShare.CURRENT_BYTES));
72909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mTimestamp = cursor.getInt(cursor.getColumnIndexOrThrow(BluetoothShare.TIMESTAMP));
73009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        info.mMediaScanned = (cursor.getInt(cursor.getColumnIndexOrThrow(Constants.MEDIA_SCANNED)) != Constants.MEDIA_SCANNED_NOT_SCANNED);
73109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
73209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (confirmed) {
733ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (V) Log.v(TAG, "Service handle info " + info.mId + " confirmed");
73409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* Inbounds transfer get user confirmation, so we start it */
735df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun            int i = findBatchWithTimeStamp(info.mTimestamp);
7369d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (i != -1) {
7379d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                BluetoothOppBatch batch = mBatchs.get(i);
7389d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                if (mServerTransfer != null && batch.mId == mServerTransfer.getBatchId()) {
7399d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                    mServerTransfer.setConfirmed();
7409d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                } //TODO need to think about else
7419d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
74209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
74309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int i = findBatchWithTimeStamp(info.mTimestamp);
74409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (i != -1) {
74509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            BluetoothOppBatch batch = mBatchs.get(i);
74609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (batch.mStatus == Constants.BATCH_STATUS_FINISHED
74709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    || batch.mStatus == Constants.BATCH_STATUS_FAILED) {
748ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "Batch " + batch.mId + " is finished");
74909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (batch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
75009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (mTransfer == null) {
75109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.e(TAG, "Unexpected error! mTransfer is null");
75209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else if (batch.mId == mTransfer.getBatchId()) {
75309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mTransfer.stop();
75409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else {
75509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.e(TAG, "Unexpected error! batch id " + batch.mId
75609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " doesn't match mTransfer id " + mTransfer.getBatchId());
75709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
7583fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan                    mTransfer.cleanup();
7599d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                    mTransfer = null;
76009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
76109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (mServerTransfer == null) {
76209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.e(TAG, "Unexpected error! mServerTransfer is null");
76309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else if (batch.mId == mServerTransfer.getBatchId()) {
76409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mServerTransfer.stop();
76509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else {
76609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.e(TAG, "Unexpected error! batch id " + batch.mId
76709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + " doesn't match mServerTransfer id "
76809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + mServerTransfer.getBatchId());
76909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
7703fafe61ef25c1899fdc817c52163aec16c31055cRavi Nagarajan                    mServerTransfer.cleanup();
7719d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                    mServerTransfer = null;
77209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
77309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                removeBatch(batch);
77409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
77509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
77609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
77709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
77809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
77909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Removes the local copy of the info about a share.
78009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
78109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void deleteShare(int arrayPos) {
7826769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
78309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
78409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
78509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * Delete arrayPos from a batch. The logic is
78609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 1) Search existing batch for the info
78709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 2) cancel the batch
78809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * 3) If the batch become empty delete the batch
78909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
79009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int i = findBatchWithTimeStamp(info.mTimestamp);
79109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (i != -1) {
79209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            BluetoothOppBatch batch = mBatchs.get(i);
79309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (batch.hasShare(info)) {
794ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "Service cancel batch for share " + info.mId);
79509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                batch.cancelBatch();
79609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
79709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (batch.isEmpty()) {
798ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "Service remove batch  " + batch.mId);
79909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                removeBatch(batch);
80009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
80109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
80209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mShares.remove(arrayPos);
80309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
80409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
80509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private String stringFromCursor(String old, Cursor cursor, String column) {
80609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int index = cursor.getColumnIndexOrThrow(column);
80709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (old == null) {
80809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return cursor.getString(index);
80909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
81009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mNewChars == null) {
81109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mNewChars = new CharArrayBuffer(128);
81209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
81309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        cursor.copyStringToBuffer(index, mNewChars);
81409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int length = mNewChars.sizeCopied;
81509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (length != old.length()) {
81609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return cursor.getString(index);
81709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
81809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mOldChars == null || mOldChars.sizeCopied < length) {
81909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mOldChars = new CharArrayBuffer(length);
82009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
82109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        char[] oldArray = mOldChars.data;
82209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        char[] newArray = mNewChars.data;
82309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        old.getChars(0, length, oldArray, 0);
82409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        for (int i = length - 1; i >= 0; --i) {
82509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (oldArray[i] != newArray[i]) {
82609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                return new String(newArray, 0, length);
82709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
82809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
82909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return old;
83009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
83109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
83209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int findBatchWithTimeStamp(long timestamp) {
83309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        for (int i = mBatchs.size() - 1; i >= 0; i--) {
83409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mBatchs.get(i).mTimestamp == timestamp) {
83509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                return i;
83609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
83709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
83809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return -1;
83909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
84009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
84109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private void removeBatch(BluetoothOppBatch batch) {
842ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "Remove batch " + batch.mId);
84309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mBatchs.remove(batch);
8449d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        BluetoothOppBatch nextBatch;
84509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mBatchs.size() > 0) {
84609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            for (int i = 0; i < mBatchs.size(); i++) {
84709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                // we have a running batch
8489d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                nextBatch = mBatchs.get(i);
8499d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                if (nextBatch.mStatus == Constants.BATCH_STATUS_RUNNING) {
85009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    return;
85109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
8521ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    // just finish a transfer, start pending outbound transfer
8539d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                    if (nextBatch.mDirection == BluetoothShare.DIRECTION_OUTBOUND) {
8549d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        if (V) Log.v(TAG, "Start pending outbound batch " + nextBatch.mId);
8559d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        mTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch);
85609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mTransfer.start();
85709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        return;
8589d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                    } else if (nextBatch.mDirection == BluetoothShare.DIRECTION_INBOUND
8599d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                            && mServerSession != null) {
8609d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        // have to support pending inbound transfer
8619d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        // if an outbound transfer and incoming socket happens together
8629d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        if (V) Log.v(TAG, "Start pending inbound batch " + nextBatch.mId);
8639d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, nextBatch,
8649d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                                                                   mServerSession);
8659d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        mServerTransfer.start();
8669d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        if (nextBatch.getPendingShare().mConfirm ==
8679d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                                BluetoothShare.USER_CONFIRMATION_CONFIRMED) {
8689d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                            mServerTransfer.setConfirmed();
8699d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        }
8709d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                        return;
87109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
87209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
87309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
87409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
87509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
87609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
87709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean needAction(int arrayPos) {
8786769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
87909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (BluetoothShare.isStatusCompleted(info.mStatus)) {
88009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return false;
88109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
88209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return true;
88309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
88409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
88509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean visibleNotification(int arrayPos) {
8866769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
88709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return info.hasCompletionNotification();
88809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
88909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
89009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean scanFile(Cursor cursor, int arrayPos) {
8916769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
8926769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        synchronized (BluetoothOppService.this) {
893ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (D) Log.d(TAG, "Scanning file " + info.mFilename);
8941ac5507790a87810061a19dadec36eb328a222eaTao Liejun            if (!mMediaScanInProgress) {
8951ac5507790a87810061a19dadec36eb328a222eaTao Liejun                mMediaScanInProgress = true;
8961ac5507790a87810061a19dadec36eb328a222eaTao Liejun                new MediaScannerNotifier(this, info, mHandler);
8971ac5507790a87810061a19dadec36eb328a222eaTao Liejun                return true;
8981ac5507790a87810061a19dadec36eb328a222eaTao Liejun            } else {
8991ac5507790a87810061a19dadec36eb328a222eaTao Liejun                return false;
9001ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
90109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
90209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
90309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
90409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean shouldScanFile(int arrayPos) {
9056769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        BluetoothOppShareInfo info = mShares.get(arrayPos);
9061ac5507790a87810061a19dadec36eb328a222eaTao Liejun        return BluetoothShare.isStatusSuccess(info.mStatus)
907d5e1472188b7e21123a02339ed8766256aa8f630Martijn Coenen                && info.mDirection == BluetoothShare.DIRECTION_INBOUND && !info.mMediaScanned &&
908d5e1472188b7e21123a02339ed8766256aa8f630Martijn Coenen                info.mConfirm != BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED;
90909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
91009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9110a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick    // Run in a background thread at boot.
9120a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick    private static void trimDatabase(ContentResolver contentResolver) {
913389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        final String INVISIBLE = BluetoothShare.VISIBILITY + "=" +
914389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                BluetoothShare.VISIBILITY_HIDDEN;
915389f6dd45f7a45b12af847a510086125777e1198Lixin Yue
916389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        // remove the invisible/complete/outbound shares
917389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        final String WHERE_INVISIBLE_COMPLETE_OUTBOUND = BluetoothShare.DIRECTION + "="
918389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.DIRECTION_OUTBOUND + " AND " + BluetoothShare.STATUS + ">="
919389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE;
9200a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        int delNum = contentResolver.delete(BluetoothShare.CONTENT_URI,
921389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                WHERE_INVISIBLE_COMPLETE_OUTBOUND, null);
922389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        if (V) Log.v(TAG, "Deleted complete outbound shares, number =  " + delNum);
923389f6dd45f7a45b12af847a510086125777e1198Lixin Yue
924389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        // remove the invisible/finished/inbound/failed shares
925389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        final String WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED = BluetoothShare.DIRECTION + "="
926389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + ">"
927389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE;
9280a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        delNum = contentResolver.delete(BluetoothShare.CONTENT_URI,
929389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                WHERE_INVISIBLE_COMPLETE_INBOUND_FAILED, null);
930389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        if (V) Log.v(TAG, "Deleted complete inbound failed shares, number = " + delNum);
931389f6dd45f7a45b12af847a510086125777e1198Lixin Yue
932389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        // Only keep the inbound and successful shares for LiverFolder use
933389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        // Keep the latest 1000 to easy db query
934389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        final String WHERE_INBOUND_SUCCESS = BluetoothShare.DIRECTION + "="
935389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.DIRECTION_INBOUND + " AND " + BluetoothShare.STATUS + "="
936389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                + BluetoothShare.STATUS_SUCCESS + " AND " + INVISIBLE;
9370a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick        Cursor cursor = contentResolver.query(BluetoothShare.CONTENT_URI, new String[] {
93809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            BluetoothShare._ID
939389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        }, WHERE_INBOUND_SUCCESS, null, BluetoothShare._ID); // sort by id
940389f6dd45f7a45b12af847a510086125777e1198Lixin Yue
94109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (cursor == null) {
94209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return;
94309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
944389f6dd45f7a45b12af847a510086125777e1198Lixin Yue
945389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        int recordNum = cursor.getCount();
946389f6dd45f7a45b12af847a510086125777e1198Lixin Yue        if (recordNum > Constants.MAX_RECORDS_IN_DATABASE) {
947389f6dd45f7a45b12af847a510086125777e1198Lixin Yue            int numToDelete = recordNum - Constants.MAX_RECORDS_IN_DATABASE;
94875fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue
94975fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue            if (cursor.moveToPosition(numToDelete)) {
950389f6dd45f7a45b12af847a510086125777e1198Lixin Yue                int columnId = cursor.getColumnIndexOrThrow(BluetoothShare._ID);
95175fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue                long id = cursor.getLong(columnId);
9520a79bdbbfa3b79b808cbbe7490731e5aae4489e9Brad Fitzpatrick                delNum = contentResolver.delete(BluetoothShare.CONTENT_URI,
95375fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue                        BluetoothShare._ID + " < " + id, null);
95475fc857d22de0ec22e082bddb720d8465c9e3552Lixin Yue                if (V) Log.v(TAG, "Deleted old inbound success share: " + delNum);
95509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
95609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
95709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        cursor.close();
95809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
95909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
96009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private static class MediaScannerNotifier implements MediaScannerConnectionClient {
96109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
96209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        private MediaScannerConnection mConnection;
96309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
96409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        private BluetoothOppShareInfo mInfo;
96509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
96609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        private Context mContext;
96709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
96809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        private Handler mCallback;
96909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
97009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public MediaScannerNotifier(Context context, BluetoothOppShareInfo info, Handler handler) {
97109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext = context;
97209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mInfo = info;
97309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mCallback = handler;
97409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mConnection = new MediaScannerConnection(mContext, this);
975ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (V) Log.v(TAG, "Connecting to MediaScannerConnection ");
97609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mConnection.connect();
97709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
97809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
97909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void onMediaScannerConnected() {
980ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (V) Log.v(TAG, "MediaScannerConnection onMediaScannerConnected");
98109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mConnection.scanFile(mInfo.mFilename, mInfo.mMimetype);
98209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
98309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
98409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        public void onScanCompleted(String path, Uri uri) {
98509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
986ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) {
98709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.v(TAG, "MediaScannerConnection onScanCompleted");
98809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.v(TAG, "MediaScannerConnection path is " + path);
98909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Log.v(TAG, "MediaScannerConnection Uri is " + uri);
99009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
99109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (uri != null) {
99209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Message msg = Message.obtain();
99309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.setTarget(mCallback);
99409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.what = MEDIA_SCANNED;
99509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.arg1 = mInfo.mId;
99609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.obj = uri;
99709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.sendToTarget();
99809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
99909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    Message msg = Message.obtain();
100009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.setTarget(mCallback);
100109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.what = MEDIA_SCANNED_FAILED;
100209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.arg1 = mInfo.mId;
100309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    msg.sendToTarget();
100409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
100509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (Exception ex) {
100609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.v(TAG, "!!!MediaScannerConnection exception: " + ex);
100709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } finally {
1008ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "MediaScannerConnection disconnect");
100909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mConnection.disconnect();
101009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
101109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
101209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
101309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly}
1014