19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.test;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Application;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Service;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.test.mock.MockApplication;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Field;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Random;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This test case provides a framework in which you can test Service classes in
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a controlled environment.  It provides basic support for the lifecycle of a
347d433aabb731a790fc8d06d260c826751215113fJoe Malin * Service, and hooks with which you can inject various dependencies and control
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the environment in which your Service is tested.
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
373aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <div class="special reference">
383aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <h3>Developer Guides</h3>
393aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <p>For more information about application testing, read the
403aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
413aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez * </div>
423aef8e1d1b2f0b87d470bcccf37ba4ebb6560c45Joe Fernandez *
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p><b>Lifecycle Support.</b>
447d433aabb731a790fc8d06d260c826751215113fJoe Malin * A Service is accessed with a specific sequence of
457aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * calls, as described in the
467aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * <a href="http://developer.android.com/guide/topics/fundamentals/services.html">Services</a>
477aee61f5a96e94e158bf5ad3d8e192c4d4f7eff6Scott Main * document. In order to support the lifecycle of a Service,
487d433aabb731a790fc8d06d260c826751215113fJoe Malin * <code>ServiceTestCase</code> enforces this protocol:
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
507d433aabb731a790fc8d06d260c826751215113fJoe Malin * <ul>
517d433aabb731a790fc8d06d260c826751215113fJoe Malin *      <li>
527d433aabb731a790fc8d06d260c826751215113fJoe Malin *          The {@link #setUp()} method is called before each test method. The base implementation
537d433aabb731a790fc8d06d260c826751215113fJoe Malin *          gets the system context. If you override <code>setUp()</code>, you must call
547d433aabb731a790fc8d06d260c826751215113fJoe Malin *          <code>super.setUp()</code> as the first statement in your override.
557d433aabb731a790fc8d06d260c826751215113fJoe Malin *      </li>
567d433aabb731a790fc8d06d260c826751215113fJoe Malin *      <li>
577d433aabb731a790fc8d06d260c826751215113fJoe Malin *          The test case waits to call {@link android.app.Service#onCreate()} until one of your
587d433aabb731a790fc8d06d260c826751215113fJoe Malin *          test methods calls {@link #startService} or {@link #bindService}.  This gives you an
597d433aabb731a790fc8d06d260c826751215113fJoe Malin *          opportunity to set up or adjust any additional framework or test logic before you test
607d433aabb731a790fc8d06d260c826751215113fJoe Malin *          the running service.
617d433aabb731a790fc8d06d260c826751215113fJoe Malin *      </li>
627d433aabb731a790fc8d06d260c826751215113fJoe Malin *      <li>
637d433aabb731a790fc8d06d260c826751215113fJoe Malin *          When one of your test methods calls {@link #startService ServiceTestCase.startService()}
647d433aabb731a790fc8d06d260c826751215113fJoe Malin *          or {@link #bindService  ServiceTestCase.bindService()}, the test case calls
657d433aabb731a790fc8d06d260c826751215113fJoe Malin *          {@link android.app.Service#onCreate() Service.onCreate()} and then calls either
667d433aabb731a790fc8d06d260c826751215113fJoe Malin *          {@link android.app.Service#startService(Intent) Service.startService(Intent)} or
677d433aabb731a790fc8d06d260c826751215113fJoe Malin *          {@link android.app.Service#bindService(Intent, ServiceConnection, int)
687d433aabb731a790fc8d06d260c826751215113fJoe Malin *          Service.bindService(Intent, ServiceConnection, int)}, as appropriate. It also stores
697d433aabb731a790fc8d06d260c826751215113fJoe Malin *          values needed to track and support the lifecycle.
707d433aabb731a790fc8d06d260c826751215113fJoe Malin *      </li>
717d433aabb731a790fc8d06d260c826751215113fJoe Malin *      <li>
727d433aabb731a790fc8d06d260c826751215113fJoe Malin *          After each test method finishes, the test case calls the {@link #tearDown} method. This
737d433aabb731a790fc8d06d260c826751215113fJoe Malin *          method stops and destroys the service with the appropriate calls, depending on how the
747d433aabb731a790fc8d06d260c826751215113fJoe Malin *          service was started. If you override <code>tearDown()</code>, your must call the
757d433aabb731a790fc8d06d260c826751215113fJoe Malin *          <code>super.tearDown()</code> as the last statement in your override.
767d433aabb731a790fc8d06d260c826751215113fJoe Malin *      </li>
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </ul>
787d433aabb731a790fc8d06d260c826751215113fJoe Malin *
797d433aabb731a790fc8d06d260c826751215113fJoe Malin * <p>
807d433aabb731a790fc8d06d260c826751215113fJoe Malin *      <strong>Dependency Injection.</strong>
817d433aabb731a790fc8d06d260c826751215113fJoe Malin *      A service has two inherent dependencies, its {@link android.content.Context Context} and its
827d433aabb731a790fc8d06d260c826751215113fJoe Malin *      associated {@link android.app.Application Application}. The ServiceTestCase framework
837d433aabb731a790fc8d06d260c826751215113fJoe Malin *      allows you to inject modified, mock, or isolated replacements for these dependencies, and
847d433aabb731a790fc8d06d260c826751215113fJoe Malin *      thus perform unit tests with controlled dependencies in an isolated environment.
857d433aabb731a790fc8d06d260c826751215113fJoe Malin * </p>
867d433aabb731a790fc8d06d260c826751215113fJoe Malin * <p>
877d433aabb731a790fc8d06d260c826751215113fJoe Malin *      By default, the test case is injected with a full system context and a generic
887d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link android.test.mock.MockApplication MockApplication} object. You can inject
897d433aabb731a790fc8d06d260c826751215113fJoe Malin *      alternatives to either of these by invoking
907d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link AndroidTestCase#setContext(Context) setContext()} or
917d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link #setApplication setApplication()}.  You must do this <em>before</em> calling
927d433aabb731a790fc8d06d260c826751215113fJoe Malin *      startService() or bindService().  The test framework provides a
937d433aabb731a790fc8d06d260c826751215113fJoe Malin *      number of alternatives for Context, including
94a45746efadd11bb7dfab026fb3c81a25fae74ca4Jeff Smith *      {@link android.test.mock.MockContext MockContext},
957d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link android.test.RenamingDelegatingContext RenamingDelegatingContext},
967d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link android.content.ContextWrapper ContextWrapper}, and
977d433aabb731a790fc8d06d260c826751215113fJoe Malin *      {@link android.test.IsolatedContext}.
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class ServiceTestCase<T extends Service> extends AndroidTestCase {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Class<T> mServiceClass;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Context mSystemContext;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Application mApplication;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1067d433aabb731a790fc8d06d260c826751215113fJoe Malin    /**
1077d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Constructor
1087d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @param serviceClass The type of the service under test.
1097d433aabb731a790fc8d06d260c826751215113fJoe Malin     */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ServiceTestCase(Class<T> serviceClass) {
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceClass = serviceClass;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private T mService;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mServiceAttached = false;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mServiceCreated = false;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mServiceStarted = false;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mServiceBound = false;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Intent mServiceIntent = null;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mServiceId;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1237d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @return An instance of the service under test. This instance is created automatically when
1247d433aabb731a790fc8d06d260c826751215113fJoe Malin     * a test calls {@link #startService} or {@link #bindService}.
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public T getService() {
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mService;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1317d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Gets the current system context and stores it.
1327d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
1337d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Extend this method to do your own test initialization. If you do so, you
1347d433aabb731a790fc8d06d260c826751215113fJoe Malin     * must call <code>super.setUp()</code> as the first statement in your override. The method is
1357d433aabb731a790fc8d06d260c826751215113fJoe Malin     * called before each test method is executed.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setUp() throws Exception {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.setUp();
1407d433aabb731a790fc8d06d260c826751215113fJoe Malin
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // get the real context, before the individual tests have a chance to muck with it
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mSystemContext = getContext();
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1457d433aabb731a790fc8d06d260c826751215113fJoe Malin
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1477d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Creates the service under test and attaches all injected dependencies
1487d433aabb731a790fc8d06d260c826751215113fJoe Malin     * (Context, Application) to it.  This is called automatically by {@link #startService} or
1497d433aabb731a790fc8d06d260c826751215113fJoe Malin     * by {@link #bindService}.
1507d433aabb731a790fc8d06d260c826751215113fJoe Malin     * If you need to call {@link AndroidTestCase#setContext(Context) setContext()} or
1517d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link #setApplication setApplication()}, do so before calling this method.
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void setupService() {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService = null;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService = mServiceClass.newInstance();
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (Exception e) {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            assertNotNull(mService);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getApplication() == null) {
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setApplication(new MockApplication());
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService.attach(
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                getContext(),
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null,               // ActivityThread not actually used in Service
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mServiceClass.getName(),
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null,               // token not needed when not talking with the activity manager
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                getApplication(),
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                null                // mocked services don't talk with the activity manager
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                );
1717d433aabb731a790fc8d06d260c826751215113fJoe Malin
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertNotNull(mService);
1737d433aabb731a790fc8d06d260c826751215113fJoe Malin
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceId = new Random().nextInt();
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceAttached = true;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1777d433aabb731a790fc8d06d260c826751215113fJoe Malin
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1797d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Starts the service under test, in the same way as if it were started by
1807d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link android.content.Context#startService(Intent) Context.startService(Intent)} with
1817d433aabb731a790fc8d06d260c826751215113fJoe Malin     * an {@link android.content.Intent} that identifies a service.
1827d433aabb731a790fc8d06d260c826751215113fJoe Malin     * If you use this method to start the service, it is automatically stopped by
1837d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link #tearDown}.
1847d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
1857d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @param intent An Intent that identifies a service, of the same form as the Intent passed to
1867d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link android.content.Context#startService(Intent) Context.startService(Intent)}.
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void startService(Intent intent) {
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mServiceAttached) {
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setupService();
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertNotNull(mService);
1937d433aabb731a790fc8d06d260c826751215113fJoe Malin
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mServiceCreated) {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService.onCreate();
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mServiceCreated = true;
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19871be4b5ed994030171fb3bd3f08fbc8c43c47567Evan Millar        mService.onStartCommand(intent, 0, mServiceId);
1997d433aabb731a790fc8d06d260c826751215113fJoe Malin
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceStarted = true;
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2037d433aabb731a790fc8d06d260c826751215113fJoe Malin    /**
2047d433aabb731a790fc8d06d260c826751215113fJoe Malin     * <p>
2057d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Starts the service under test, in the same way as if it were started by
2067d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      {@link android.content.Context#bindService(Intent, ServiceConnection, int)
2077d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Context.bindService(Intent, ServiceConnection, flags)} with an
2087d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      {@link android.content.Intent} that identifies a service.
2097d433aabb731a790fc8d06d260c826751215113fJoe Malin     * </p>
2107d433aabb731a790fc8d06d260c826751215113fJoe Malin     * <p>
2117d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Notice that the parameters are different. You do not provide a
2127d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      {@link android.content.ServiceConnection} object or the flags parameter. Instead,
2137d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      you only provide the Intent. The method returns an object whose type is a
2147d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      subclass of {@link android.os.IBinder}, or null if the method fails. An IBinder
2157d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      object refers to a communication channel between the application and
2167d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      the service. The flag is assumed to be {@link android.content.Context#BIND_AUTO_CREATE}.
2177d433aabb731a790fc8d06d260c826751215113fJoe Malin     * </p>
2187d433aabb731a790fc8d06d260c826751215113fJoe Malin     * <p>
21940eee61e25fb887f5267686f8a0a7c5bd9f95769Scott Main     *      See <a href="{@docRoot}guide/components/aidl.html">Designing a Remote Interface
2207d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Using AIDL</a> for more information about the communication channel object returned
2217d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      by this method.
2227d433aabb731a790fc8d06d260c826751215113fJoe Malin     * </p>
2237d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Note:  To be able to use bindService in a test, the service must implement getService()
2247d433aabb731a790fc8d06d260c826751215113fJoe Malin     * method. An example of this is in the ApiDemos sample application, in the
2257d433aabb731a790fc8d06d260c826751215113fJoe Malin     * LocalService demo.
2267d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
2277d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @param intent An Intent object of the form expected by
2287d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link android.content.Context#bindService}.
2297d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
2307d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @return An object whose type is a subclass of IBinder, for making further calls into
2317d433aabb731a790fc8d06d260c826751215113fJoe Malin     * the service.
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected IBinder bindService(Intent intent) {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mServiceAttached) {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setupService();
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertNotNull(mService);
2387d433aabb731a790fc8d06d260c826751215113fJoe Malin
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mServiceCreated) {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService.onCreate();
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mServiceCreated = true;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // no extras are expected by unbind
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceIntent = intent.cloneFilter();
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IBinder result = mService.onBind(intent);
2467d433aabb731a790fc8d06d260c826751215113fJoe Malin
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mServiceBound = true;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2507d433aabb731a790fc8d06d260c826751215113fJoe Malin
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2527d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Makes the necessary calls to stop (or unbind) the service under test, and
2537d433aabb731a790fc8d06d260c826751215113fJoe Malin     * calls onDestroy().  Ordinarily this is called automatically (by {@link #tearDown}, but
2547d433aabb731a790fc8d06d260c826751215113fJoe Malin     * you can call it directly from your test in order to check for proper shutdown behavior.
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void shutdownService() {
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mServiceStarted) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService.stopSelf();
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mServiceStarted = false;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mServiceBound) {
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService.onUnbind(mServiceIntent);
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mServiceBound = false;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mServiceCreated) {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mService.onDestroy();
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2687d433aabb731a790fc8d06d260c826751215113fJoe Malin
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2707d433aabb731a790fc8d06d260c826751215113fJoe Malin     * <p>
2717d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Shuts down the service under test.  Ensures all resources are cleaned up and
2727d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      garbage collected before moving on to the next test. This method is called after each
2737d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      test method.
2747d433aabb731a790fc8d06d260c826751215113fJoe Malin     * </p>
2757d433aabb731a790fc8d06d260c826751215113fJoe Malin     * <p>
2767d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      Subclasses that override this method must call <code>super.tearDown()</code> as their
2777d433aabb731a790fc8d06d260c826751215113fJoe Malin     *      last statement.
2787d433aabb731a790fc8d06d260c826751215113fJoe Malin     * </p>
2797d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws Exception
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void tearDown() throws Exception {
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        shutdownService();
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService = null;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2877d433aabb731a790fc8d06d260c826751215113fJoe Malin        // Scrub out members - protects against memory leaks in the case where someone
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // creates a non-static inner class (thus referencing the test case) and gives it to
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // someone else to hold onto
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        scrubClass(ServiceTestCase.class);
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.tearDown();
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2947d433aabb731a790fc8d06d260c826751215113fJoe Malin
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2967d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Sets the application that is used during the test.  If you do not call this method,
2977d433aabb731a790fc8d06d260c826751215113fJoe Malin     * a new {@link android.test.mock.MockApplication MockApplication} object is used.
2987d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
2997d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @param application The Application object that is used by the service under test.
3007d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
3017d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @see #getApplication()
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setApplication(Application application) {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mApplication = application;
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3087d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Returns the Application object in use by the service under test.
3097d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
3107d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @return The application object.
3117d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setApplication
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Application getApplication() {
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mApplication;
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3177d433aabb731a790fc8d06d260c826751215113fJoe Malin
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3197d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Returns the real system context that is saved by {@link #setUp()}. Use it to create
3207d433aabb731a790fc8d06d260c826751215113fJoe Malin     * mock or other types of context objects for the service under test.
3217d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
3227d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @return A normal system context.
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Context getSystemContext() {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mSystemContext;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3287d433aabb731a790fc8d06d260c826751215113fJoe Malin    /**
3297d433aabb731a790fc8d06d260c826751215113fJoe Malin     * Tests that {@link #setupService()} runs correctly and issues an
3307d433aabb731a790fc8d06d260c826751215113fJoe Malin     * {@link junit.framework.Assert#assertNotNull(String, Object)} if it does.
3317d433aabb731a790fc8d06d260c826751215113fJoe Malin     * You can override this test method if you wish.
3327d433aabb731a790fc8d06d260c826751215113fJoe Malin     *
3337d433aabb731a790fc8d06d260c826751215113fJoe Malin     * @throws Exception
3347d433aabb731a790fc8d06d260c826751215113fJoe Malin     */
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void testServiceTestCaseSetUpProperly() throws Exception {
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setupService();
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        assertNotNull("service should be launched successfully", mService);
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
340