1e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk/*
2340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * Copyright (C) 2017 The Android Open Source Project
3e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk *
4e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * except in compliance with the License. You may obtain a copy of the License at
6e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk *
7e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk *      http://www.apache.org/licenses/LICENSE-2.0
8e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk *
9e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * Unless required by applicable law or agreed to in writing, software distributed under the
10e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * KIND, either express or implied. See the License for the specific language governing
12e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk * permissions and limitations under the License.
13e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk */
14e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
15340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkpackage android.testing;
16e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
179abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.BroadcastReceiver;
189abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.ComponentCallbacks;
193cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monkimport android.content.ComponentName;
20e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monkimport android.content.ContentProviderClient;
21e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monkimport android.content.Context;
22e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monkimport android.content.ContextWrapper;
239abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.Intent;
249abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.IntentFilter;
259abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.content.ServiceConnection;
2626bc8996c88cfc828afa95e22efee0fed82d8780Jason Monkimport android.content.pm.PackageManager;
273cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monkimport android.content.res.Resources;
289abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.Handler;
293cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monkimport android.os.IBinder;
309abca5e9f88c47579f8334c6c48741a259185b9bJason Monkimport android.os.UserHandle;
31e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monkimport android.provider.Settings;
323cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monkimport android.util.ArrayMap;
33aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monkimport android.view.LayoutInflater;
34e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
35340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport org.junit.rules.TestRule;
36340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport org.junit.rules.TestWatcher;
37340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport org.junit.runner.Description;
38340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkimport org.junit.runners.model.Statement;
399abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
40340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk/**
41340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * A ContextWrapper with utilities specifically designed to make Testing easier.
42340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *
43340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <ul>
44340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <li>System services can be mocked out with {@link #addMockSystemService}</li>
45340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <li>Service binding can be mocked out with {@link #addMockService}</li>
46f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk * <li>Settings support {@link TestableSettingsProvider}</li>
47340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <li>Has support for {@link LeakCheck} for services and receivers</li>
48340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * </ul>
49340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk *
50340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <p>TestableContext should be defined as a rule on your test so it can clean up after itself.
51340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * Like the following:</p>
52340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * <pre class="prettyprint">
53340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * {@literal
54340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * @Rule
55340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * private final TestableContext mContext = new TestableContext(InstrumentationRegister.getContext());
56340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * }
57340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk * </pre>
58340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk */
59340b0e5216b4fcc435e0459b1ca46155a572100dJason Monkpublic class TestableContext extends ContextWrapper implements TestRule {
60e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
61340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private final TestableContentResolver mTestableContentResolver;
62f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk    private final TestableSettingsProvider mSettingsProvider;
63e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
643cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    private ArrayMap<String, Object> mMockSystemServices;
653cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    private ArrayMap<ComponentName, IBinder> mMockServices;
663cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    private ArrayMap<ServiceConnection, ComponentName> mActiveServices;
673cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
6826bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    private PackageManager mMockPackageManager;
69340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private LeakCheck.Tracker mReceiver;
70340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private LeakCheck.Tracker mService;
71340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    private LeakCheck.Tracker mComponent;
72340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
73340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public TestableContext(Context base) {
74340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        this(base, null);
75340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    }
769abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
77340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public TestableContext(Context base, LeakCheck check) {
78e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk        super(base);
79340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mTestableContentResolver = new TestableContentResolver(base);
80e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk        ContentProviderClient settings = base.getContentResolver()
81e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk                .acquireContentProviderClient(Settings.AUTHORITY);
82f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk        mSettingsProvider = TestableSettingsProvider.getFakeSettingsProvider(settings);
83f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk        mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider);
84340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mReceiver = check != null ? check.getTracker("receiver") : null;
85340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mService = check != null ? check.getTracker("service") : null;
86340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        mComponent = check != null ? check.getTracker("component") : null;
87e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    }
88e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
8926bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    public void setMockPackageManager(PackageManager mock) {
9026bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk        mMockPackageManager = mock;
9126bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    }
9226bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk
9326bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    @Override
9426bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    public PackageManager getPackageManager() {
9526bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk        if (mMockPackageManager != null) {
9626bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk            return mMockPackageManager;
9726bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk        }
9826bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk        return super.getPackageManager();
9926bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk    }
10026bc8996c88cfc828afa95e22efee0fed82d8780Jason Monk
1013cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    @Override
1023cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    public Resources getResources() {
1033cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        return super.getResources();
1043cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
1053cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
1069125068a991b24d27810b6392a562b32457b3f5dAdrian Roos    public <T> void addMockSystemService(Class<T> service, T mock) {
1079125068a991b24d27810b6392a562b32457b3f5dAdrian Roos        addMockSystemService(getSystemServiceName(service), mock);
1089125068a991b24d27810b6392a562b32457b3f5dAdrian Roos    }
1099125068a991b24d27810b6392a562b32457b3f5dAdrian Roos
1103cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    public void addMockSystemService(String name, Object service) {
111340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (mMockSystemServices == null) mMockSystemServices = new ArrayMap<>();
1123cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        mMockSystemServices.put(name, service);
1133cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
1143cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
1153cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    public void addMockService(ComponentName component, IBinder service) {
116340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        if (mMockServices == null) mMockServices = new ArrayMap<>();
1173cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        mMockServices.put(component, service);
1183cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
1193cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
1203cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    @Override
1213cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    public Object getSystemService(String name) {
1223cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (mMockSystemServices != null && mMockSystemServices.containsKey(name)) {
1233cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            return mMockSystemServices.get(name);
1243cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        }
125aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk        if (name.equals(LAYOUT_INFLATER_SERVICE)) {
126aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk            return getBaseContext().getSystemService(LayoutInflater.class).cloneInContext(this);
127aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk        }
1283cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        return super.getSystemService(name);
1293cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
1303cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
131f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk    TestableSettingsProvider getSettingsProvider() {
132e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk        return mSettingsProvider;
133e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    }
134e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
135e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    @Override
136340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public TestableContentResolver getContentResolver() {
137340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        return mTestableContentResolver;
138e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    }
139e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk
140e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    @Override
141e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    public Context getApplicationContext() {
142e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk        // Return this so its always a TestableContext.
143e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk        return this;
144e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk    }
1459abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1469abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1479abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
1489abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
1499abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.registerReceiver(receiver, filter);
1509abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1519abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1529abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1539abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
1549abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            String broadcastPermission, Handler scheduler) {
1559abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
1569abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.registerReceiver(receiver, filter, broadcastPermission, scheduler);
1579abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1589abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1599abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1609abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
1619abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            IntentFilter filter, String broadcastPermission, Handler scheduler) {
1629abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mReceiver != null) mReceiver.getLeakInfo(receiver).addAllocation(new Throwable());
1639abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
1649abca5e9f88c47579f8334c6c48741a259185b9bJason Monk                scheduler);
1659abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1669abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1679abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1689abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void unregisterReceiver(BroadcastReceiver receiver) {
1699abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mReceiver != null) mReceiver.getLeakInfo(receiver).clearAllocations();
1709abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        super.unregisterReceiver(receiver);
1719abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1729abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1739abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1749abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
1759abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
1763cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (checkMocks(service.getComponent(), conn)) return true;
1779abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.bindService(service, conn, flags);
1789abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1799abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1809abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1819abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
1829abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            Handler handler, UserHandle user) {
1839abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
1843cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (checkMocks(service.getComponent(), conn)) return true;
1859abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.bindServiceAsUser(service, conn, flags, handler, user);
1869abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1879abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1889abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
1899abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
1909abca5e9f88c47579f8334c6c48741a259185b9bJason Monk            UserHandle user) {
1919abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mService != null) mService.getLeakInfo(conn).addAllocation(new Throwable());
1923cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (checkMocks(service.getComponent(), conn)) return true;
1939abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        return super.bindServiceAsUser(service, conn, flags, user);
1949abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
1959abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
1963cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    private boolean checkMocks(ComponentName component, ServiceConnection conn) {
1973cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (mMockServices != null && component != null && mMockServices.containsKey(component)) {
198340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            if (mActiveServices == null) mActiveServices = new ArrayMap<>();
1993cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            mActiveServices.put(conn, component);
2003cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            conn.onServiceConnected(component, mMockServices.get(component));
2013cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            return true;
2023cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        }
2033cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        return false;
2043cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
2053cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
2069abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
2079abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void unbindService(ServiceConnection conn) {
2089abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mService != null) mService.getLeakInfo(conn).clearAllocations();
2093cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        if (mActiveServices != null && mActiveServices.containsKey(conn)) {
2103cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            conn.onServiceDisconnected(mActiveServices.get(conn));
2113cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            mActiveServices.remove(conn);
2123cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk            return;
2133cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        }
2149abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        super.unbindService(conn);
2159abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
2169abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2173cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    public boolean isBound(ComponentName component) {
2183cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk        return mActiveServices != null && mActiveServices.containsValue(component);
2193cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk    }
2203cfedd78b1e3704481de27d7354cb29b2fb43781Jason Monk
2219abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
2229abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void registerComponentCallbacks(ComponentCallbacks callback) {
2239abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mComponent != null) mComponent.getLeakInfo(callback).addAllocation(new Throwable());
2249abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        super.registerComponentCallbacks(callback);
2259abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
2269abca5e9f88c47579f8334c6c48741a259185b9bJason Monk
2279abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    @Override
2289abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    public void unregisterComponentCallbacks(ComponentCallbacks callback) {
2299abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        if (mComponent != null) mComponent.getLeakInfo(callback).clearAllocations();
2309abca5e9f88c47579f8334c6c48741a259185b9bJason Monk        super.unregisterComponentCallbacks(callback);
2319abca5e9f88c47579f8334c6c48741a259185b9bJason Monk    }
23249fa016a98cef9940c883b3f620a0e90537a204eJason Monk
233340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    @Override
234340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk    public Statement apply(Statement base, Description description) {
235340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        return new TestWatcher() {
236340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            @Override
237340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            protected void succeeded(Description description) {
238f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk                mSettingsProvider.clearValuesAndCheck(TestableContext.this);
239340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
240340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk
241340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            @Override
242340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            protected void failed(Throwable e, Description description) {
243f06a317039a6502252c2b4b1a878520d166a38c6Jason Monk                mSettingsProvider.clearValuesAndCheck(TestableContext.this);
244340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk            }
245340b0e5216b4fcc435e0459b1ca46155a572100dJason Monk        }.apply(base, description);
24649fa016a98cef9940c883b3f620a0e90537a204eJason Monk    }
247e97892844a5c21c91c7f82b96f82202b18a1a24dJason Monk}
248