Merge "Skip service timeout if the host process has been killed." into udc-dev am: 08386a5893

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22067066

Change-Id: I61fe35097b947a8194416beff0a02b9e66b01d3d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Jing Ji
2023-03-15 01:23:19 +00:00
committed by Automerger Merge Worker
4 changed files with 235 additions and 13 deletions

View File

@@ -252,12 +252,6 @@ public final class ActiveServices {
private static final boolean LOG_SERVICE_START_STOP = DEBUG_SERVICE; private static final boolean LOG_SERVICE_START_STOP = DEBUG_SERVICE;
// How long we wait for a service to finish executing.
static final int SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
// How long we wait for a service to finish executing.
static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;
// Foreground service types that always get immediate notification display, // Foreground service types that always get immediate notification display,
// expressed in the same bitmask format that ServiceRecord.foregroundServiceType // expressed in the same bitmask format that ServiceRecord.foregroundServiceType
// uses. // uses.
@@ -6609,13 +6603,15 @@ public final class ActiveServices {
return; return;
} }
final ProcessServiceRecord psr = proc.mServices; final ProcessServiceRecord psr = proc.mServices;
if (psr.numberOfExecutingServices() == 0 || proc.getThread() == null) { if (psr.numberOfExecutingServices() == 0 || proc.getThread() == null
|| proc.isKilled()) {
return; return;
} }
final long now = SystemClock.uptimeMillis(); final long now = SystemClock.uptimeMillis();
final long maxTime = now final long maxTime = now
- (psr.shouldExecServicesFg() - (psr.shouldExecServicesFg()
? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT); ? mAm.mConstants.SERVICE_TIMEOUT
: mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT);
ServiceRecord timeout = null; ServiceRecord timeout = null;
long nextTime = 0; long nextTime = 0;
for (int i = psr.numberOfExecutingServices() - 1; i >= 0; i--) { for (int i = psr.numberOfExecutingServices() - 1; i >= 0; i--) {
@@ -6646,8 +6642,8 @@ public final class ActiveServices {
ActivityManagerService.SERVICE_TIMEOUT_MSG); ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc; msg.obj = proc;
mAm.mHandler.sendMessageAtTime(msg, psr.shouldExecServicesFg() mAm.mHandler.sendMessageAtTime(msg, psr.shouldExecServicesFg()
? (nextTime + SERVICE_TIMEOUT) : ? (nextTime + mAm.mConstants.SERVICE_TIMEOUT) :
(nextTime + SERVICE_BACKGROUND_TIMEOUT)); (nextTime + mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT));
} }
} }
@@ -6743,7 +6739,7 @@ public final class ActiveServices {
ActivityManagerService.SERVICE_TIMEOUT_MSG); ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc; msg.obj = proc;
mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg() mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg()
? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT); ? mAm.mConstants.SERVICE_TIMEOUT : mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT);
} }
void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) { void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {

View File

@@ -248,7 +248,16 @@ final class ActivityManagerConstants extends ContentObserver {
private static final long DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS = 15 * 1000; private static final long DEFAULT_SERVICE_BIND_ALMOST_PERCEPTIBLE_TIMEOUT_MS = 15 * 1000;
// Flag stored in the DeviceConfig API. /**
* Default value to {@link #SERVICE_TIMEOUT}.
*/
private static final long DEFAULT_SERVICE_TIMEOUT = 20 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
/**
* Default value to {@link #SERVICE_BACKGROUND_TIMEOUT}.
*/
private static final long DEFAULT_SERVICE_BACKGROUND_TIMEOUT = DEFAULT_SERVICE_TIMEOUT * 10;
/** /**
* Maximum number of cached processes. * Maximum number of cached processes.
*/ */
@@ -506,6 +515,12 @@ final class ActivityManagerConstants extends ContentObserver {
// to restart less than this amount of time from the last one. // to restart less than this amount of time from the last one.
public long SERVICE_MIN_RESTART_TIME_BETWEEN = DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN; public long SERVICE_MIN_RESTART_TIME_BETWEEN = DEFAULT_SERVICE_MIN_RESTART_TIME_BETWEEN;
// How long we wait for a service to finish executing.
long SERVICE_TIMEOUT = DEFAULT_SERVICE_TIMEOUT;
// How long we wait for a service to finish executing.
long SERVICE_BACKGROUND_TIMEOUT = DEFAULT_SERVICE_BACKGROUND_TIMEOUT;
// Maximum amount of time for there to be no activity on a service before // Maximum amount of time for there to be no activity on a service before
// we consider it non-essential and allow its process to go on the // we consider it non-essential and allow its process to go on the
// LRU background list. // LRU background list.

View File

@@ -989,9 +989,16 @@ public class ApplicationExitInfoTest {
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid, private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid,
int connectionGroup, int procState, long pss, long rss, int connectionGroup, int procState, long pss, long rss,
String processName, String packageName) { String processName, String packageName) {
return makeProcessRecord(pid, uid, packageUid, definingUid, connectionGroup,
procState, pss, rss, processName, packageName, mAms);
}
static ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid,
int connectionGroup, int procState, long pss, long rss,
String processName, String packageName, ActivityManagerService ams) {
ApplicationInfo ai = new ApplicationInfo(); ApplicationInfo ai = new ApplicationInfo();
ai.packageName = packageName; ai.packageName = packageName;
ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid); ProcessRecord app = new ProcessRecord(ams, ai, processName, uid);
app.setPid(pid); app.setPid(pid);
app.info.uid = packageUid; app.info.uid = packageUid;
if (definingUid != null) { if (definingUid != null) {

View File

@@ -0,0 +1,204 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static com.android.server.am.ApplicationExitInfoTest.makeProcessRecord;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.after;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.IApplicationThread;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.DropBoxManagerInternal;
import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService.Injector;
import com.android.server.am.ApplicationExitInfoTest.ServiceThreadRule;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
/**
* Test class for the service timeout.
*
* Build/Install/Run:
* atest ServiceTimeoutTest
*/
@Presubmit
public final class ServiceTimeoutTest {
private static final String TAG = ServiceTimeoutTest.class.getSimpleName();
private static final long DEFAULT_SERVICE_TIMEOUT = 2000;
@Rule
public final ServiceThreadRule mServiceThreadRule = new ServiceThreadRule();
private Context mContext;
private HandlerThread mHandlerThread;
@Mock
private AppOpsService mAppOpsService;
@Mock
private DropBoxManagerInternal mDropBoxManagerInt;
@Mock
private PackageManagerInternal mPackageManagerInt;
@Mock
private UsageStatsManagerInternal mUsageStatsManagerInt;
private ActivityManagerService mAms;
private ProcessList mProcessList;
private ActiveServices mActiveServices;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mProcessList = spy(new ProcessList());
LocalServices.removeServiceForTest(DropBoxManagerInternal.class);
LocalServices.addService(DropBoxManagerInternal.class, mDropBoxManagerInt);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
final ActivityManagerService realAms = new ActivityManagerService(
new TestInjector(mContext), mServiceThreadRule.getThread());
realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal());
realAms.mOomAdjuster.mCachedAppOptimizer = spy(realAms.mOomAdjuster.mCachedAppOptimizer);
realAms.mPackageManagerInt = mPackageManagerInt;
realAms.mUsageStatsService = mUsageStatsManagerInt;
realAms.mProcessesReady = true;
realAms.mConstants.SERVICE_TIMEOUT = DEFAULT_SERVICE_TIMEOUT;
realAms.mConstants.SERVICE_BACKGROUND_TIMEOUT = DEFAULT_SERVICE_TIMEOUT;
mAms = spy(realAms);
}
@After
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(DropBoxManagerInternal.class);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
mHandlerThread.quit();
}
@SuppressWarnings("GuardedBy")
@Test
public void testServiceTimeoutAndProcessKill() throws Exception {
final int pid = 12345;
final int uid = 10123;
final String name = "com.example.foo";
final ProcessRecord app = makeProcessRecord(
pid, // pid
uid, // uid
uid, // packageUid
null, // definingUid
0, // connectionGroup
PROCESS_STATE_SERVICE, // procstate
0, // pss
0, // rss
name, // processName
name, // packageName
mAms);
app.makeActive(mock(IApplicationThread.class), mAms.mProcessStats);
mProcessList.updateLruProcessLocked(app, false, null);
final long now = SystemClock.uptimeMillis();
final ServiceRecord sr = spy(ServiceRecord.newEmptyInstanceForTest(mAms));
doNothing().when(sr).dump(any(), anyString());
sr.startRequested = true;
sr.executingStart = now;
app.mServices.startExecutingService(sr);
mActiveServices.scheduleServiceTimeoutLocked(app);
verify(mActiveServices, timeout(DEFAULT_SERVICE_TIMEOUT * 2).times(1))
.serviceTimeout(eq(app));
clearInvocations(mActiveServices);
app.mServices.startExecutingService(sr);
mActiveServices.scheduleServiceTimeoutLocked(app);
app.killLocked(TAG, 42, false);
mAms.removeLruProcessLocked(app);
verify(mActiveServices, after(DEFAULT_SERVICE_TIMEOUT * 4)
.times(1)).serviceTimeout(eq(app));
}
private class TestInjector extends Injector {
TestInjector(Context context) {
super(context);
}
@Override
public AppOpsService getAppOpsService(File recentAccessesFile, File storageFile,
Handler handler) {
return mAppOpsService;
}
@Override
public Handler getUiHandler(ActivityManagerService service) {
return mHandlerThread.getThreadHandler();
}
@Override
public ProcessList getProcessList(ActivityManagerService service) {
return mProcessList;
}
@Override
public ActiveServices getActiveServices(ActivityManagerService service) {
if (mActiveServices == null) {
mActiveServices = spy(new ActiveServices(service));
}
return mActiveServices;
}
}
}