10d4fc55861ed4393aa82f124f2865695ef564641Marc Blank/*
20d4fc55861ed4393aa82f124f2865695ef564641Marc Blank /*
30d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * Copyright (C) 2011 The Android Open Source Project
40d4fc55861ed4393aa82f124f2865695ef564641Marc Blank *
50d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * Licensed under the Apache License, Version 2.0 (the "License");
60d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * you may not use this file except in compliance with the License.
70d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * You may obtain a copy of the License at
80d4fc55861ed4393aa82f124f2865695ef564641Marc Blank *
90d4fc55861ed4393aa82f124f2865695ef564641Marc Blank *      http://www.apache.org/licenses/LICENSE-2.0
100d4fc55861ed4393aa82f124f2865695ef564641Marc Blank *
110d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * Unless required by applicable law or agreed to in writing, software
120d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * distributed under the License is distributed on an "AS IS" BASIS,
130d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * See the License for the specific language governing permissions and
150d4fc55861ed4393aa82f124f2865695ef564641Marc Blank * limitations under the License.
160d4fc55861ed4393aa82f124f2865695ef564641Marc Blank */
170d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
180d4fc55861ed4393aa82f124f2865695ef564641Marc Blankpackage com.android.emailcommon.service;
190d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
200d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.content.ComponentName;
210d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.content.Context;
220d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.content.Intent;
230d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.content.ServiceConnection;
24bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Leeimport android.content.pm.ProviderInfo;
254da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Huimport android.os.AsyncTask;
260d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.os.Debug;
270d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.os.IBinder;
28b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedyimport android.os.Looper;
290d4fc55861ed4393aa82f124f2865695ef564641Marc Blankimport android.os.RemoteException;
30560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy
31fb9deb96c3af56bf422e28e8ae3b7b838f343155Tony Mantlerimport com.android.emailcommon.provider.EmailContent;
32560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedyimport com.android.mail.utils.LogUtils;
330d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
340d4fc55861ed4393aa82f124f2865695ef564641Marc Blank/**
354da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * ServiceProxy is a superclass for proxy objects which make a single call to a service. It handles
364da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * connecting to the service, running a task supplied by the subclass when the connection is ready,
374da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * and disconnecting from the service afterwards. ServiceProxy objects cannot be reused (trying to
384da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * do so generates an {@link IllegalStateException}).
390d4fc55861ed4393aa82f124f2865695ef564641Marc Blank *
404da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * Subclasses must override {@link #onConnected} to store the binder. Then, when the subclass wants
414da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * to make a service call, it should call {@link #setTask}, supplying the {@link ProxyTask} that
424da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * should run when the connection is ready. {@link ProxyTask#run} should implement the necessary
434da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu * logic to make the call on the service.
440d4fc55861ed4393aa82f124f2865695ef564641Marc Blank */
450d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
460d4fc55861ed4393aa82f124f2865695ef564641Marc Blankpublic abstract class ServiceProxy {
4724bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon    public static final String EXTRA_FORCE_SHUTDOWN = "ServiceProxy.FORCE_SHUTDOWN";
4824bb2dabd9dd7d8bd39fed53f312ae6034e373bbMartin Hibdon
49da3c4b8261825063ddf081e9335823569b813bd3Marc Blank    private static final boolean DEBUG_PROXY = false; // DO NOT CHECK THIS IN SET TO TRUE
50fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank    private final String mTag;
510d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
520d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private final Context mContext;
530d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    protected final Intent mIntent;
540d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private ProxyTask mTask;
550d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private String mName = " unnamed";
560d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private final ServiceConnection mConnection = new ProxyConnection();
570d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    // Service call timeout (in seconds)
580d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private int mTimeout = 45;
59fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank    private long mStartTime;
604da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    private boolean mTaskSet = false;
614da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    private boolean mTaskCompleted = false;
620d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
63e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    public static Intent getIntentForEmailPackage(Context context, String actionName) {
64bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee        /**
65bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         * We want to scope the intent so that only the Email app will handle it. Unfortunately
66bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         * we found that there are many instances where the package name of the Email app is
67bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         * not what we expect. The easiest way to find the package of the correct app is to
68bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         * see who is the EmailContent.AUTHORITY as there is only one app that can implement
69bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         * the content provider for this authority and this is the right app to handle this intent.
70bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee         */
71fb9deb96c3af56bf422e28e8ae3b7b838f343155Tony Mantler        final Intent intent = new Intent(EmailContent.EMAIL_PACKAGE_NAME + "." + actionName);
72bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee        final ProviderInfo info = context.getPackageManager().resolveContentProvider(
73bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee                EmailContent.AUTHORITY, 0);
74bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee        if (info != null) {
75bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee            final String packageName = info.packageName;
76bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee            intent.setPackage(packageName);
77bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee        } else {
78bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee            LogUtils.e(LogUtils.TAG, "Could not find the Email Content Provider");
79bca4f9fcfb2301cd4bfdb9a4785f299f90e4263cAnthony Lee        }
80fb9deb96c3af56bf422e28e8ae3b7b838f343155Tony Mantler        return intent;
81e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank    }
82e714bb9d153cfe13a7f0932e7d67ea08fa5a1d98Marc Blank
834da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    /**
844da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * This function is called after the proxy connects to the service but before it runs its task.
854da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * Subclasses must override this to store the binder correctly.
864da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * @param binder The service IBinder.
874da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     */
880d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    public abstract void onConnected(IBinder binder);
890d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
900d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    public ServiceProxy(Context _context, Intent _intent) {
910d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        mContext = _context;
920d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        mIntent = _intent;
93fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank        mTag = getClass().getSimpleName();
940d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        if (Debug.isDebuggerConnected()) {
950d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            mTimeout <<= 2;
960d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
970d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
980d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
990d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    private class ProxyConnection implements ServiceConnection {
1004da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu        @Override
1010d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        public void onServiceConnected(ComponentName name, IBinder binder) {
1020d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            if (DEBUG_PROXY) {
103560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                LogUtils.v(mTag, "Connected: " + name.getShortClassName() + " at " +
1040b5f15d61ebf7c0e8428100637bc479ed93a4cb2Marc Blank                        (System.currentTimeMillis() - mStartTime) + "ms");
1050d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            }
1064da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu
1074da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            // Let subclasses handle the binder.
1084da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            onConnected(binder);
1094da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu
1104da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            // Do our work in another thread.
1114da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            new AsyncTask<Void, Void, Void>() {
1124da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                @Override
1134da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                protected Void doInBackground(Void... params) {
1144da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    try {
1154da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        mTask.run();
1164da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    } catch (RemoteException e) {
1174da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    }
1188ba8c1648c38cd339b09501a057fc2f5b0658b10Marc Blank                    try {
1194da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        // Each ServiceProxy handles just one task, so we unbind after we're
1204da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        // done with our work.
1214da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        mContext.unbindService(mConnection);
1226ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                    } catch (RuntimeException e) {
1236ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // The exceptions that are thrown here look like IllegalStateException,
1246ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // IllegalArgumentException and RuntimeException. Catching RuntimeException
1256ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // which get them all. Reasons for these exceptions include services that
1266ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // have already been stopped or unbound. This can happen if the user ended
1276ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // the activity that was using the service. This is harmless, but we've got
1286ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        // to catch it.
1296ef1621f444538337253f3aeae63dfe0098e238bAnthony Lee                        LogUtils.e(mTag, e, "RuntimeException when trying to unbind from service");
1304da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    }
1314da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    mTaskCompleted = true;
1324da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    synchronized(mConnection) {
1334da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        if (DEBUG_PROXY) {
134560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                            LogUtils.v(mTag, "Task " + mName + " completed; disconnecting");
1354da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        }
1364da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        mConnection.notify();
1378ba8c1648c38cd339b09501a057fc2f5b0658b10Marc Blank                    }
1384da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                    return null;
1394da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                }
1404da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            }.execute();
1410d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
1420d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1434da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu        @Override
1440d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        public void onServiceDisconnected(ComponentName name) {
1450d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            if (DEBUG_PROXY) {
146560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                LogUtils.v(mTag, "Disconnected: " + name.getShortClassName() + " at " +
1470b5f15d61ebf7c0e8428100637bc479ed93a4cb2Marc Blank                        (System.currentTimeMillis() - mStartTime) + "ms");
1480d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            }
1490d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
1500d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
1510d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1524da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    protected interface ProxyTask {
1530d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        public void run() throws RemoteException;
1540d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
1550d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1560d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    public ServiceProxy setTimeout(int secs) {
1570d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        mTimeout = secs;
1580d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        return this;
1590d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
1600d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1610d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    public int getTimeout() {
1620d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        return mTimeout;
1630d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
1640d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1654da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    protected boolean setTask(ProxyTask task, String name) throws IllegalStateException {
1664da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu        if (mTaskSet) {
1674da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu            throw new IllegalStateException("Cannot call setTask twice on the same ServiceProxy.");
1680d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
1694da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu        mTaskSet = true;
1700d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        mName = name;
1710d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        mTask = task;
172fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank        mStartTime = System.currentTimeMillis();
1730d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        if (DEBUG_PROXY) {
174560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy            LogUtils.v(mTag, "Bind requested for task " + mName);
1750d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
1760d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        return mContext.bindService(mIntent, mConnection, Context.BIND_AUTO_CREATE);
1770d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
1780d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
1794da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    /**
1804da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * Callers that want to wait on the {@link ProxyTask} should call this immediately after calling
1814da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * {@link #setTask}. This will wait until the task completes, up to the timeout (which can be
1824da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     * set with {@link #setTimeout}).
1834da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu     */
1844da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu    protected void waitForCompletion() {
185b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy        /*
186b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy         * onServiceConnected() is always called on the main thread, and we block the current thread
187b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy         * for up to 10 seconds as a timeout. If we're currently on the main thread,
188b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy         * onServiceConnected() is not called until our timeout elapses (and the UI is frozen for
189b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy         * the duration).
190b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy         */
191b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy        if (Looper.myLooper() == Looper.getMainLooper()) {
192b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy            throw new IllegalStateException("This cannot be called on the main thread.");
193b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy        }
194b34608228f0b55e401415b67b8150ca9e00cee7dScott Kennedy
1950d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        synchronized (mConnection) {
1960d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            long time = System.currentTimeMillis();
1970d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            try {
1980d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                if (DEBUG_PROXY) {
199560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                    LogUtils.v(mTag, "Waiting for task " + mName + " to complete...");
2000d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                }
2010d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                mConnection.wait(mTimeout * 1000L);
2020d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            } catch (InterruptedException e) {
2030d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                // Can be ignored safely
2040d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            }
2050d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            if (DEBUG_PROXY) {
206560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                LogUtils.v(mTag, "Wait for " + mName +
2074da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                        (mTaskCompleted ? " finished in " : " timed out in ") +
208fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank                        (System.currentTimeMillis() - time) + "ms");
2090d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            }
2100d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
2110d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
2120d4fc55861ed4393aa82f124f2865695ef564641Marc Blank
2130d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    /**
2140d4fc55861ed4393aa82f124f2865695ef564641Marc Blank     * Connection test; return indicates whether the remote service can be connected to
2150d4fc55861ed4393aa82f124f2865695ef564641Marc Blank     * @return the result of trying to connect to the remote service
2160d4fc55861ed4393aa82f124f2865695ef564641Marc Blank     */
2170d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    public boolean test() {
2180d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        try {
2190d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            return setTask(new ProxyTask() {
2204da36412922f19e63638c593537a2bf64ab57bd8Yu Ping Hu                @Override
2210d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                public void run() throws RemoteException {
2220d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                    if (DEBUG_PROXY) {
223560bfadc3151f7a06f3b06e9a6c92cfa534c63ecScott Kennedy                        LogUtils.v(mTag, "Connection test succeeded in " +
224fdec974c93817988a00248b7d223ec9f7f20ecb8Marc Blank                                (System.currentTimeMillis() - mStartTime) + "ms");
2250d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                    }
2260d4fc55861ed4393aa82f124f2865695ef564641Marc Blank                }
2270d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            }, "test");
2280d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        } catch (Exception e) {
2290d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            // For any failure, return false.
2300d4fc55861ed4393aa82f124f2865695ef564641Marc Blank            return false;
2310d4fc55861ed4393aa82f124f2865695ef564641Marc Blank        }
2320d4fc55861ed4393aa82f124f2865695ef564641Marc Blank    }
2330d4fc55861ed4393aa82f124f2865695ef564641Marc Blank}
234