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