1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ondevicepersonalization.services; 18 19 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; 20 21 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 22 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.AGGREGATE_ERROR_DATA_REPORTING_JOB_ID; 23 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.MAINTENANCE_TASK_JOB_ID; 24 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.MDD_CELLULAR_CHARGING_PERIODIC_TASK_JOB_ID; 25 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.MDD_CHARGING_PERIODIC_TASK_JOB_ID; 26 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.MDD_MAINTENANCE_PERIODIC_TASK_JOB_ID; 27 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.MDD_WIFI_CHARGING_PERIODIC_TASK_JOB_ID; 28 import static com.android.ondevicepersonalization.services.OnDevicePersonalizationConfig.USER_DATA_COLLECTION_ID; 29 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.assertNotNull; 32 import static org.junit.Assert.assertNull; 33 import static org.junit.Assert.assertTrue; 34 import static org.mockito.ArgumentMatchers.any; 35 import static org.mockito.Mockito.never; 36 import static org.mockito.Mockito.when; 37 38 import android.app.job.JobScheduler; 39 import android.content.ComponentName; 40 import android.content.Context; 41 import android.content.Intent; 42 43 import androidx.test.core.app.ApplicationProvider; 44 45 import com.android.dx.mockito.inline.extended.ExtendedMockito; 46 import com.android.modules.utils.testing.ExtendedMockitoRule; 47 import com.android.odp.module.common.DeviceUtils; 48 import com.android.ondevicepersonalization.services.data.errors.AggregateErrorDataReportingJob; 49 import com.android.ondevicepersonalization.services.data.user.UserDataCollectionJob; 50 import com.android.ondevicepersonalization.services.download.mdd.MobileDataDownloadFactory; 51 import com.android.ondevicepersonalization.services.maintenance.OnDevicePersonalizationMaintenanceJob; 52 53 import com.google.common.collect.ImmutableList; 54 import com.google.common.util.concurrent.ListeningExecutorService; 55 import com.google.common.util.concurrent.MoreExecutors; 56 57 import org.junit.Before; 58 import org.junit.Rule; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import org.junit.runners.JUnit4; 62 import org.mockito.Mock; 63 import org.mockito.quality.Strictness; 64 65 @RunWith(JUnit4.class) 66 public class OnDevicePersonalizationBroadcastReceiverTests { 67 private static final Intent BOOT_COMPLETED_INTENT = new Intent(Intent.ACTION_BOOT_COMPLETED); 68 69 /** All the jobs that the BroadcastReceiver is responsible for scheduling. */ 70 private static final ImmutableList<Integer> JOB_IDS = 71 ImmutableList.of( 72 // Job Ids for ODP maintenance jobs that are scheduled/cancelled by the 73 // receiver. 74 MAINTENANCE_TASK_JOB_ID, 75 AGGREGATE_ERROR_DATA_REPORTING_JOB_ID, 76 USER_DATA_COLLECTION_ID, 77 // Job Ids for various Mdd Jobs 78 MDD_MAINTENANCE_PERIODIC_TASK_JOB_ID, 79 MDD_CHARGING_PERIODIC_TASK_JOB_ID, 80 MDD_CELLULAR_CHARGING_PERIODIC_TASK_JOB_ID, 81 MDD_WIFI_CHARGING_PERIODIC_TASK_JOB_ID); 82 83 private final Context mContext = ApplicationProvider.getApplicationContext(); 84 85 // Use direct executor to keep all work sequential for the tests 86 private final ListeningExecutorService mDirectExecutorService = 87 MoreExecutors.newDirectExecutorService(); 88 89 private final JobScheduler mJobScheduler = mContext.getSystemService(JobScheduler.class); 90 91 private final OnDevicePersonalizationBroadcastReceiver mReceiverUnderTest = 92 new OnDevicePersonalizationBroadcastReceiver(mDirectExecutorService); 93 @Mock private Flags mMockFlags; 94 95 @Rule 96 public final ExtendedMockitoRule mExtendedMockitoRule = 97 new ExtendedMockitoRule.Builder(this) 98 .spyStatic(FlagsFactory.class) 99 .spyStatic(DeviceUtils.class) 100 .spyStatic(AggregateErrorDataReportingJob.class) 101 .spyStatic(OnDevicePersonalizationMaintenanceJob.class) 102 .spyStatic(UserDataCollectionJob.class) 103 .setStrictness(Strictness.LENIENT) 104 .build(); 105 106 @Before setup()107 public void setup() throws Exception { 108 ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags); 109 when(mMockFlags.getGlobalKillSwitch()).thenReturn(false); 110 111 // By default, disable SPE and aggregate error reporting. 112 when(mMockFlags.getSpePilotJobEnabled()).thenReturn(false); 113 when(mMockFlags.getSpeOnAggregateErrorDataReportingJobEnabled()).thenReturn(false); 114 when(mMockFlags.getAggregatedErrorReportingEnabled()).thenReturn(false); 115 116 ExtendedMockito.doReturn(true).when(() -> DeviceUtils.isOdpSupported(any())); 117 118 // Cancel any pending maintenance and MDD jobs 119 for (int jobId : JOB_IDS) { 120 mJobScheduler.cancel(jobId); 121 } 122 } 123 124 @Test testOnReceive()125 public void testOnReceive() { 126 when(mMockFlags.getAggregatedErrorReportingEnabled()).thenReturn(true); 127 MobileDataDownloadFactory.getMdd(mContext, mDirectExecutorService, mDirectExecutorService); 128 129 mReceiverUnderTest.onReceive(mContext, BOOT_COMPLETED_INTENT); 130 131 verify(() -> OnDevicePersonalizationMaintenanceJob.schedule(mContext)); 132 verify(() -> UserDataCollectionJob.schedule(mContext)); 133 verify(() -> AggregateErrorDataReportingJob.schedule(mContext)); 134 assertAllJobsScheduled(); 135 } 136 137 @Test testOnReceiveKillSwitchOn()138 public void testOnReceiveKillSwitchOn() { 139 when(mMockFlags.getGlobalKillSwitch()).thenReturn(true); 140 141 mReceiverUnderTest.onReceive(mContext, BOOT_COMPLETED_INTENT); 142 143 verify(() -> OnDevicePersonalizationMaintenanceJob.schedule(mContext), never()); 144 verify(() -> UserDataCollectionJob.schedule(mContext), never()); 145 verify(() -> AggregateErrorDataReportingJob.schedule(mContext), never()); 146 assertNoJobsScheduled(); 147 } 148 149 @Test testOnReceiveDeviceNotSupported()150 public void testOnReceiveDeviceNotSupported() { 151 ExtendedMockito.doReturn(false).when(() -> DeviceUtils.isOdpSupported(any())); 152 153 mReceiverUnderTest.onReceive(mContext, BOOT_COMPLETED_INTENT); 154 155 verify(() -> OnDevicePersonalizationMaintenanceJob.schedule(mContext), never()); 156 verify(() -> UserDataCollectionJob.schedule(mContext), never()); 157 verify(() -> AggregateErrorDataReportingJob.schedule(mContext), never()); 158 assertNoJobsScheduled(); 159 } 160 161 @Test testOnReceiveInvalidIntent()162 public void testOnReceiveInvalidIntent() { 163 mReceiverUnderTest.onReceive(mContext, new Intent(Intent.ACTION_DIAL_EMERGENCY)); 164 165 verify(() -> OnDevicePersonalizationMaintenanceJob.schedule(mContext), never()); 166 verify(() -> UserDataCollectionJob.schedule(mContext), never()); 167 verify(() -> AggregateErrorDataReportingJob.schedule(mContext), never()); 168 assertNoJobsScheduled(); 169 } 170 171 @Test testEnableReceiver()172 public void testEnableReceiver() { 173 ComponentName componentName = 174 new ComponentName(mContext, OnDevicePersonalizationBroadcastReceiver.class); 175 176 assertTrue(OnDevicePersonalizationBroadcastReceiver.enableReceiver(mContext)); 177 int result = mContext.getPackageManager().getComponentEnabledSetting(componentName); 178 assertEquals(COMPONENT_ENABLED_STATE_ENABLED, result); 179 } 180 assertAllJobsScheduled()181 private void assertAllJobsScheduled() { 182 for (int jobId : JOB_IDS) { 183 assertNotNull(mJobScheduler.getPendingJob(jobId)); 184 } 185 } 186 assertNoJobsScheduled()187 private void assertNoJobsScheduled() { 188 for (int jobId : JOB_IDS) { 189 assertNull(mJobScheduler.getPendingJob(jobId)); 190 } 191 } 192 } 193