1 /* 2 * Copyright (C) 2023 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.server.am; 18 19 import static android.app.ActivityManager.PROCESS_STATE_SERVICE; 20 21 import static com.android.server.am.ApplicationExitInfoTest.makeProcessRecord; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.ArgumentMatchers.eq; 26 import static org.mockito.Mockito.after; 27 import static org.mockito.Mockito.clearInvocations; 28 import static org.mockito.Mockito.doNothing; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.mock; 31 import static org.mockito.Mockito.spy; 32 import static org.mockito.Mockito.timeout; 33 import static org.mockito.Mockito.times; 34 import static org.mockito.Mockito.verify; 35 36 import android.app.IApplicationThread; 37 import android.app.usage.UsageStatsManagerInternal; 38 import android.content.ComponentName; 39 import android.content.Context; 40 import android.content.pm.PackageManagerInternal; 41 import android.os.Handler; 42 import android.os.HandlerThread; 43 import android.os.SystemClock; 44 import android.platform.test.annotations.Presubmit; 45 46 import androidx.test.platform.app.InstrumentationRegistry; 47 48 import com.android.server.DropBoxManagerInternal; 49 import com.android.server.LocalServices; 50 import com.android.server.am.ActivityManagerService.Injector; 51 import com.android.server.am.ApplicationExitInfoTest.ServiceThreadRule; 52 import com.android.server.appop.AppOpsService; 53 import com.android.server.wm.ActivityTaskManagerService; 54 55 import org.junit.After; 56 import org.junit.Before; 57 import org.junit.Rule; 58 import org.junit.Test; 59 import org.mockito.Mock; 60 import org.mockito.MockitoAnnotations; 61 62 import java.io.File; 63 64 /** 65 * Test class for the service timeout. 66 * 67 * Build/Install/Run: 68 * atest ServiceTimeoutTest 69 */ 70 @Presubmit 71 public final class ServiceTimeoutTest { 72 private static final String TAG = ServiceTimeoutTest.class.getSimpleName(); 73 private static final long DEFAULT_SERVICE_TIMEOUT = 2000; 74 75 @Rule 76 public final ServiceThreadRule mServiceThreadRule = new ServiceThreadRule(); 77 private Context mContext; 78 private HandlerThread mHandlerThread; 79 80 @Mock 81 private AppOpsService mAppOpsService; 82 @Mock 83 private DropBoxManagerInternal mDropBoxManagerInt; 84 @Mock 85 private PackageManagerInternal mPackageManagerInt; 86 @Mock 87 private UsageStatsManagerInternal mUsageStatsManagerInt; 88 89 private ActivityManagerService mAms; 90 private ProcessList mProcessList; 91 private ActiveServices mActiveServices; 92 93 @Before setUp()94 public void setUp() throws Exception { 95 MockitoAnnotations.initMocks(this); 96 97 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 98 99 mHandlerThread = new HandlerThread(TAG); 100 mHandlerThread.start(); 101 mProcessList = spy(new ProcessList()); 102 103 LocalServices.removeServiceForTest(DropBoxManagerInternal.class); 104 LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt); 105 LocalServices.removeServiceForTest(PackageManagerInternal.class); 106 LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt); 107 doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent(); 108 109 final ActivityManagerService realAms = new ActivityManagerService( 110 new TestInjector(mContext), mServiceThreadRule.getThread()); 111 realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext); 112 realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper()); 113 realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal()); 114 realAms.mOomAdjuster.mCachedAppOptimizer = spy(realAms.mOomAdjuster.mCachedAppOptimizer); 115 realAms.mPackageManagerInt = mPackageManagerInt; 116 realAms.mUsageStatsService = mUsageStatsManagerInt; 117 realAms.mProcessesReady = true; 118 realAms.mConstants.SERVICE_TIMEOUT = DEFAULT_SERVICE_TIMEOUT; 119 realAms.mConstants.SERVICE_BACKGROUND_TIMEOUT = DEFAULT_SERVICE_TIMEOUT; 120 mAms = spy(realAms); 121 } 122 123 @After tearDown()124 public void tearDown() throws Exception { 125 LocalServices.removeServiceForTest(DropBoxManagerInternal.class); 126 LocalServices.removeServiceForTest(PackageManagerInternal.class); 127 mHandlerThread.quit(); 128 } 129 130 @SuppressWarnings("GuardedBy") 131 @Test testServiceTimeoutAndProcessKill()132 public void testServiceTimeoutAndProcessKill() throws Exception { 133 final int pid = 12345; 134 final int uid = 10123; 135 final String name = "com.example.foo"; 136 final ProcessRecord app = makeProcessRecord( 137 pid, // pid 138 uid, // uid 139 uid, // packageUid 140 null, // definingUid 141 0, // connectionGroup 142 PROCESS_STATE_SERVICE, // procstate 143 0, // pss 144 0, // rss 145 name, // processName 146 name, // packageName 147 mAms); 148 app.makeActive(mock(IApplicationThread.class), mAms.mProcessStats); 149 mProcessList.updateLruProcessLocked(app, false, null); 150 151 final long now = SystemClock.uptimeMillis(); 152 final ServiceRecord sr = spy(ServiceRecord.newEmptyInstanceForTest(mAms)); 153 doNothing().when(sr).dump(any(), anyString()); 154 sr.startRequested = true; 155 sr.executingStart = now; 156 157 app.mServices.startExecutingService(sr); 158 mActiveServices.scheduleServiceTimeoutLocked(app); 159 160 verify(mActiveServices, timeout(DEFAULT_SERVICE_TIMEOUT * 2).times(1)) 161 .serviceTimeout(eq(app)); 162 163 clearInvocations(mActiveServices); 164 165 app.mServices.startExecutingService(sr); 166 mActiveServices.scheduleServiceTimeoutLocked(app); 167 168 app.killLocked(TAG, 42, false); 169 mAms.removeLruProcessLocked(app); 170 171 verify(mActiveServices, after(DEFAULT_SERVICE_TIMEOUT * 4) 172 .times(1)).serviceTimeout(eq(app)); 173 } 174 175 private class TestInjector extends Injector { TestInjector(Context context)176 TestInjector(Context context) { 177 super(context); 178 } 179 180 @Override getAppOpsService(File recentAccessesFile, File storageFile, Handler handler)181 public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile, 182 Handler handler) { 183 return mAppOpsService; 184 } 185 186 @Override getUiHandler(ActivityManagerService service)187 public Handler getUiHandler(ActivityManagerService service) { 188 return mHandlerThread.getThreadHandler(); 189 } 190 191 @Override getProcessList(ActivityManagerService service)192 public ProcessList getProcessList(ActivityManagerService service) { 193 return mProcessList; 194 } 195 196 @Override getActiveServices(ActivityManagerService service)197 public ActiveServices getActiveServices(ActivityManagerService service) { 198 if (mActiveServices == null) { 199 mActiveServices = spy(new ActiveServices(service)); 200 } 201 return mActiveServices; 202 } 203 } 204 } 205