Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adcc1094 authored by Jing Ji's avatar Jing Ji Committed by Automerger Merge Worker
Browse files

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

parents 0afc9f17 08386a58
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -252,12 +252,6 @@ public final class ActiveServices {

    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,
    // expressed in the same bitmask format that ServiceRecord.foregroundServiceType
    // uses.
@@ -6609,13 +6603,15 @@ public final class ActiveServices {
                    return;
                }
                final ProcessServiceRecord psr = proc.mServices;
                if (psr.numberOfExecutingServices() == 0 || proc.getThread() == null) {
                if (psr.numberOfExecutingServices() == 0 || proc.getThread() == null
                        || proc.isKilled()) {
                    return;
                }
                final long now = SystemClock.uptimeMillis();
                final long maxTime =  now
                        - (psr.shouldExecServicesFg()
                        ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
                        ? mAm.mConstants.SERVICE_TIMEOUT
                        : mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT);
                ServiceRecord timeout = null;
                long nextTime = 0;
                for (int i = psr.numberOfExecutingServices() - 1; i >= 0; i--) {
@@ -6646,8 +6642,8 @@ public final class ActiveServices {
                            ActivityManagerService.SERVICE_TIMEOUT_MSG);
                    msg.obj = proc;
                    mAm.mHandler.sendMessageAtTime(msg, psr.shouldExecServicesFg()
                            ? (nextTime + SERVICE_TIMEOUT) :
                            (nextTime + SERVICE_BACKGROUND_TIMEOUT));
                            ? (nextTime + mAm.mConstants.SERVICE_TIMEOUT) :
                            (nextTime + mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT));
                }
            }

@@ -6743,7 +6739,7 @@ public final class ActiveServices {
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        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) {
+16 −1
Original line number Diff line number Diff line
@@ -248,7 +248,16 @@ final class ActivityManagerConstants extends ContentObserver {

    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.
     */
@@ -506,6 +515,12 @@ final class ActivityManagerConstants extends ContentObserver {
    // 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;

    // 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
    // we consider it non-essential and allow its process to go on the
    // LRU background list.
+8 −1
Original line number Diff line number Diff line
@@ -989,9 +989,16 @@ public class ApplicationExitInfoTest {
    private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, Integer definingUid,
            int connectionGroup, int procState, long pss, long rss,
            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();
        ai.packageName = packageName;
        ProcessRecord app = new ProcessRecord(mAms, ai, processName, uid);
        ProcessRecord app = new ProcessRecord(ams, ai, processName, uid);
        app.setPid(pid);
        app.info.uid = packageUid;
        if (definingUid != null) {
+204 −0
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}