1f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein/*
2f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * Copyright (C) 2016 The Android Open Source Project
3f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein *
4f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * Licensed under the Apache License, Version 2.0 (the "License");
5f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * you may not use this file except in compliance with the License.
6f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * You may obtain a copy of the License at
7f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein *
8f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein *      http://www.apache.org/licenses/LICENSE-2.0
9f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein *
10f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * Unless required by applicable law or agreed to in writing, software
11f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * distributed under the License is distributed on an "AS IS" BASIS,
12f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * See the License for the specific language governing permissions and
14f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein * limitations under the License.
15f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein */
16f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
17f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinpackage com.android.settings;
18f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
19f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static org.junit.Assert.*;
20f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static org.mockito.Matchers.*;
21f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static org.mockito.Mockito.verify;
22f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static org.mockito.Mockito.when;
23f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
24f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
25f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
26f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
27f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.EXTRA_SET_ALARM;
28f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
29f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHERING_INVALID;
30f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHERING_USB;
31f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHERING_WIFI;
32f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
33f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
34f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
35f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.app.Activity;
36f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.app.AlarmManager;
37f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.app.PendingIntent;
38b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport android.app.usage.UsageStatsManager;
39f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.BroadcastReceiver;
40f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.Context;
41f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.ContextWrapper;
42f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.Intent;
43f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.IntentFilter;
44b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport android.content.pm.ActivityInfo;
45b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport android.content.pm.ApplicationInfo;
46b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport android.content.pm.ResolveInfo;
47b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport android.content.pm.PackageManager;
48f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.SharedPreferences;
49f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.SharedPreferences.Editor;
50f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.content.res.Resources;
51f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.net.ConnectivityManager;
52f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.net.wifi.WifiConfiguration;
53f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.net.wifi.WifiManager;
54f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.os.Bundle;
55f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.os.ResultReceiver;
56f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.os.SystemClock;
57f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.test.ServiceTestCase;
58f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.test.mock.MockResources;
59f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport android.util.Log;
60f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
61f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport com.android.settings.TetherService;
62f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
63f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport org.mockito.ArgumentCaptor;
64f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport org.mockito.Captor;
65f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport org.mockito.Mock;
66f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport org.mockito.MockitoAnnotations;
67f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
68f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinimport java.lang.ref.WeakReference;
69b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport java.util.ArrayList;
70b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport java.util.HashSet;
71b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport java.util.List;
72b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Kleinimport java.util.Set;
73f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
74f6b6713d7717998a60f767b274386f701cde1593Jeremy Kleinpublic class TetherServiceTest extends ServiceTestCase<TetherService> {
75f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
76f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final String TAG = "TetherServiceTest";
77b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    private static final String FAKE_PACKAGE_NAME = "com.some.package.name";
78b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    private static final String ENTITLEMENT_PACKAGE_NAME = "com.some.entitlement.name";
79f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final String TEST_RESPONSE_ACTION = "testProvisioningResponseAction";
80f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final String TEST_NO_UI_ACTION = "testNoUiProvisioningRequestAction";
81f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final int BOGUS_RECEIVER_RESULT = -5;
82f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final int TEST_CHECK_PERIOD = 100;
83f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final int MS_PER_HOUR = 60 * 60 * 1000;
84f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final int SHORT_TIMEOUT = 100;
85f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final int PROVISION_TIMEOUT = 1000;
86f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
87f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private TetherService mService;
88f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private MockResources mResources;
89b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    private FakeUsageStatsManagerWrapper mUsageStatsManagerWrapper;
90f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    int mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
91f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private int mLastTetherRequestType = TETHERING_INVALID;
92f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private int mProvisionResponse = BOGUS_RECEIVER_RESULT;
93f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private ProvisionReceiver mProvisionReceiver;
94f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private Receiver mResultReceiver;
95f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
96f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Mock private AlarmManager mAlarmManager;
97f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Mock private ConnectivityManager mConnectivityManager;
98b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    @Mock private PackageManager mPackageManager;
99f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Mock private WifiManager mWifiManager;
100f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Mock private SharedPreferences mPrefs;
101f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Mock private Editor mPrefEditor;
102f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Captor private ArgumentCaptor<PendingIntent> mPiCaptor;
103f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Captor private ArgumentCaptor<String> mStoredTypes;
104f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
105f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public TetherServiceTest() {
106f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        super(TetherService.class);
107f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
108f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
109f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Override
110f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    protected void setUp() throws Exception {
111f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        super.setUp();
112f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        MockitoAnnotations.initMocks(this);
113f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
114f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mResources = new MockResources();
115f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mContext = new TestContextWrapper(getContext());
116f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        setContext(mContext);
117f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
118f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mResultReceiver = new Receiver(this);
119f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
120f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mProvisionResponse = Activity.RESULT_OK;
121f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mProvisionReceiver = new ProvisionReceiver();
122f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        IntentFilter filter = new IntentFilter(TEST_NO_UI_ACTION);
123f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        filter.addCategory(Intent.CATEGORY_DEFAULT);
124f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mContext.registerReceiver(mProvisionReceiver, filter);
125f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
126f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        final String CURRENT_TYPES = "currentTethers";
127f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        when(mPrefs.getString(CURRENT_TYPES, "")).thenReturn("");
128f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        when(mPrefs.edit()).thenReturn(mPrefEditor);
129f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        when(mPrefEditor.putString(eq(CURRENT_TYPES), mStoredTypes.capture())).thenReturn(
130f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                mPrefEditor);
131b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        mUsageStatsManagerWrapper = new FakeUsageStatsManagerWrapper(mContext);
132b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
133b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        ResolveInfo systemAppResolveInfo = new ResolveInfo();
134b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        ActivityInfo systemActivityInfo = new ActivityInfo();
135b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        systemActivityInfo.packageName = ENTITLEMENT_PACKAGE_NAME;
136b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        ApplicationInfo systemAppInfo = new ApplicationInfo();
137b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
138b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        systemActivityInfo.applicationInfo = systemAppInfo;
139b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        systemAppResolveInfo.activityInfo = systemActivityInfo;
140b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
141b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        ResolveInfo nonSystemResolveInfo = new ResolveInfo();
142b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        ActivityInfo nonSystemActivityInfo = new ActivityInfo();
143b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        nonSystemActivityInfo.packageName = FAKE_PACKAGE_NAME;
144b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        nonSystemActivityInfo.applicationInfo = new ApplicationInfo();
145b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        nonSystemResolveInfo.activityInfo = nonSystemActivityInfo;
146b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
147b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        List<ResolveInfo> resolvers = new ArrayList();
148b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        resolvers.add(nonSystemResolveInfo);
149b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        resolvers.add(systemAppResolveInfo);
150b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        when(mPackageManager.queryBroadcastReceivers(
151b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein                any(Intent.class), eq(PackageManager.MATCH_ALL))).thenReturn(resolvers);
152f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
153f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
154f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    @Override
155f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    protected void tearDown() throws Exception {
156f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mContext.unregisterReceiver(mProvisionReceiver);
157f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        super.tearDown();
158f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
159f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
160f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private void cancelAllProvisioning() {
161f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        int[] types = new int[]{TETHERING_BLUETOOTH, TETHERING_WIFI, TETHERING_USB};
162f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        for (int type : types) {
163f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            Intent intent = new Intent();
164f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            intent.putExtra(EXTRA_REM_TETHER_TYPE, type);
165f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            startService(intent);
166f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
167f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
168f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
169f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testStartForProvision() {
170f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_WIFI);
171f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
172f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
173f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
174f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
175f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
176b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    public void testStartKeepsProvisionAppActive() {
177b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        setupService();
178b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        getService().setUsageStatsManagerWrapper(mUsageStatsManagerWrapper);
179b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
180b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        runProvisioningForType(TETHERING_WIFI);
181b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
182b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
183b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
184b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        assertFalse(mUsageStatsManagerWrapper.isAppInactive(ENTITLEMENT_PACKAGE_NAME));
185b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        // Non-system handler of the intent action should stay idle.
186b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        assertTrue(mUsageStatsManagerWrapper.isAppInactive(FAKE_PACKAGE_NAME));
187b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    }
188b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
189f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testScheduleRechecks() {
190f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        Intent intent = new Intent();
191f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
192f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_SET_ALARM, true);
193f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        startService(intent);
194f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
195f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        long period = TEST_CHECK_PERIOD * MS_PER_HOUR;
196f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        verify(mAlarmManager).setRepeating(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
197f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                eq(period), mPiCaptor.capture());
198f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        PendingIntent pi = mPiCaptor.getValue();
199f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
200f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
201f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
202f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testStartMultiple() {
203f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_WIFI);
204f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
205f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
206f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
207f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
208f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_USB);
209f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
210f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_USB));
211f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
212f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
213f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_BLUETOOTH);
214f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
215f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_BLUETOOTH));
216f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
217f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
218f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
219f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testPersistTypes() {
220f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_WIFI);
221f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
222f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        waitForProvisionRequest(TETHERING_WIFI);
223f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        waitForProvisionResponse(TETHER_ERROR_NO_ERROR);
224f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
225f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_BLUETOOTH);
226f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
227f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        waitForProvisionRequest(TETHERING_BLUETOOTH);
228f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        waitForProvisionResponse(TETHER_ERROR_NO_ERROR);
229f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
230f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        shutdownService();
231f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertEquals(TETHERING_WIFI + "," + TETHERING_BLUETOOTH, mStoredTypes.getValue());
232f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
233f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
234f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testFailureStopsTethering_Wifi() {
235f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mProvisionResponse = Activity.RESULT_CANCELED;
236f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
237f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_WIFI);
238f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
239f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
240f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
241f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
242868114891840ab0fb35a8e33f752335e505b774cJeremy Klein        verify(mConnectivityManager).stopTethering(ConnectivityManager.TETHERING_WIFI);
243f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
244f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
245f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testFailureStopsTethering_Usb() {
246f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        mProvisionResponse = Activity.RESULT_CANCELED;
247f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
248f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_USB);
249f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
250f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_USB));
251f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
252f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
253f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        verify(mConnectivityManager).setUsbTethering(eq(false));
254f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
255f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
256f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    public void testCancelAlarm() {
257f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        runProvisioningForType(TETHERING_WIFI);
258f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
259f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionRequest(TETHERING_WIFI));
260f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
261f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
262f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        Intent intent = new Intent();
263f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_REM_TETHER_TYPE, TETHERING_WIFI);
264f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        startService(intent);
265f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
266f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        verify(mAlarmManager).cancel(mPiCaptor.capture());
267f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        PendingIntent pi = mPiCaptor.getValue();
268f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
269f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
270f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
271f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private void runProvisioningForType(int type) {
272f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        Intent intent = new Intent();
273f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
274f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_RUN_PROVISION, true);
275f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
276f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        startService(intent);
277f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
278f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
279b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    private boolean waitForAppInactive(UsageStatsManager usageStatsManager, String packageName) {
280b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        long startTime = SystemClock.uptimeMillis();
281b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        while (true) {
282b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            if (usageStatsManager.isAppInactive(packageName)) {
283b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein                return true;
284b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            }
285b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
286b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein                return false;
287b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            }
288b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            SystemClock.sleep(SHORT_TIMEOUT);
289b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        }
290b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    }
291b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
292f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private boolean waitForProvisionRequest(int expectedType) {
293f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        long startTime = SystemClock.uptimeMillis();
294f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        while (true) {
295f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if (mLastTetherRequestType == expectedType) {
296f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                mLastTetherRequestType = -1;
297f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return true;
298f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
299f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
300f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                Log.v(TAG, String.format(
301f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                        "waitForProvisionRequest timeout: expected=%d, actual=%d",
302f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                        expectedType, mLastTetherRequestType));
303f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return false;
304f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
305f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            SystemClock.sleep(SHORT_TIMEOUT);
306f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
307f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
308f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
309f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private boolean waitForProvisionResponse(int expectedValue) {
310f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        long startTime = SystemClock.uptimeMillis();
311f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        while (true) {
312f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if (mLastReceiverResultCode == expectedValue) {
313f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
314f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return true;
315f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
316f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
317f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                Log.v(TAG, String.format(
318f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                        "waitForProvisionResponse timeout: expected=%d, actual=%d",
319f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                        expectedValue, mLastReceiverResultCode));
320f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return false;
321f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
322f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            SystemClock.sleep(SHORT_TIMEOUT);
323f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
324f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
325f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
326f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static class MockResources extends android.test.mock.MockResources {
327f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
328f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public int getInteger(int id) {
329f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            switch(id) {
330f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                case com.android.internal.R.integer.config_mobile_hotspot_provision_check_period:
331f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    return TEST_CHECK_PERIOD;
332f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                default:
333f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    return 0;
334f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
335f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
336f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
337f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
338f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public String getString(int id) {
339f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            switch(id) {
340f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                case com.android.internal.R.string.config_mobile_hotspot_provision_response:
341f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    return TEST_RESPONSE_ACTION;
342f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                case com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui:
343f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    return TEST_NO_UI_ACTION;
344f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                default:
345f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    return null;
346f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
347f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
348f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
349f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
350f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private class TestContextWrapper extends ContextWrapper {
351f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
352f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public TestContextWrapper(Context base) {
353f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            super(base);
354f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
355f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
356f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
357f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public Resources getResources() {
358f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            return mResources;
359f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
360f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
361f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
362f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public SharedPreferences getSharedPreferences(String name, int mode) {
363f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            // Stub out prefs to control the persisted tether type list.
364f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if (name == "tetherPrefs") {
365f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return mPrefs;
366f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
367f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            return super.getSharedPreferences(name, mode);
368f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
369f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
370f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
371b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        public PackageManager getPackageManager() {
372b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            return mPackageManager;
373b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        }
374b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
375b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        @Override
376f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public Object getSystemService(String name) {
377f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if (ALARM_SERVICE.equals(name)) {
378f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return mAlarmManager;
379f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            } else if (CONNECTIVITY_SERVICE.equals(name)) {
380f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return mConnectivityManager;
381f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            } else if (WIFI_SERVICE.equals(name)) {
382f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                return mWifiManager;
383f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
384f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
385f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            return super.getSystemService(name);
386f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
387f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
388f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
389f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private static final class Receiver extends ResultReceiver {
390f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        final WeakReference<TetherServiceTest> mTest;
391f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
392f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        Receiver(TetherServiceTest test) {
393f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            super(null);
394f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            mTest = new WeakReference<TetherServiceTest>(test);
395f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
396f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
397f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
398f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        protected void onReceiveResult(int resultCode, Bundle resultData) {
399f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            TetherServiceTest test = mTest.get();
400f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            if (test != null) {
401f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                test.mLastReceiverResultCode = resultCode;
402f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            }
403f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
404f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    };
405f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
406f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    /**
407f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein     * Stubs out the provisioning app receiver.
408f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein     */
409f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    private class ProvisionReceiver extends BroadcastReceiver {
410f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        @Override
411f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        public void onReceive(Context context, Intent intent) {
412f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            mLastTetherRequestType = intent.getIntExtra("TETHER_TYPE", TETHERING_INVALID);
413f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            sendResponse(mProvisionResponse, context);
414f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
415f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein
416f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        private void sendResponse(int response, Context context) {
417f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            Intent responseIntent = new Intent(TEST_RESPONSE_ACTION);
418f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            responseIntent.putExtra(TetherService.EXTRA_RESULT, response);
419f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein            context.sendBroadcast(
420f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein                    responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);
421f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein        }
422f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein    }
423b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
424b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    private static class FakeUsageStatsManagerWrapper
425b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            extends TetherService.UsageStatsManagerWrapper {
426b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        private final Set<String> mActivePackages;
427b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
428b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        FakeUsageStatsManagerWrapper(Context context) {
429b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            super(context);
430b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            mActivePackages = new HashSet<>();
431b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        }
432b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
433b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        @Override
434b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        void setAppInactive(String packageName, boolean isInactive) {
435b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            if (!isInactive) {
436b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein                mActivePackages.add(packageName);
437b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            } else {
438b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein                mActivePackages.remove(packageName);
439b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            }
440b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        }
441b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein
442b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        boolean isAppInactive(String packageName) {
443b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein            return !mActivePackages.contains(packageName);
444b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein        }
445b04fae204e5d356f53ea2654e039ddfbb159549dJeremy Klein    }
446f6b6713d7717998a60f767b274386f701cde1593Jeremy Klein}
447