/*
 * Copyright (C) 2017 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 android.app.cts;

import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NETWORK;
import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static android.app.stubs.LocalForegroundService.ACTION_START_FGS_RESULT;
import static android.app.stubs.LocalForegroundServiceSticky.ACTION_RESTART_FGS_STICKY_RESULT;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

import android.accessibilityservice.AccessibilityService;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Instrumentation;
import android.app.Service;
import android.app.cts.android.app.cts.tools.ServiceConnectionHandler;
import android.app.cts.android.app.cts.tools.ServiceProcessController;
import android.app.cts.android.app.cts.tools.SyncOrderedBroadcast;
import android.app.cts.android.app.cts.tools.UidImportanceListener;
import android.app.cts.android.app.cts.tools.WaitForBroadcast;
import android.app.cts.android.app.cts.tools.WatchUidRunner;
import android.app.stubs.CommandReceiver;
import android.app.stubs.LocalForegroundServiceLocation;
import android.app.stubs.LocalForegroundServiceSticky;
import android.app.stubs.ScreenOnActivity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.permission.cts.PermissionUtils;
import android.platform.test.annotations.Presubmit;
import android.server.wm.WindowManagerState;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.compatibility.common.util.AmMonitor;
import com.android.compatibility.common.util.SystemUtil;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;

@RunWith(AndroidJUnit4.class)
@Presubmit
public class ActivityManagerProcessStateTest {
    private static final String TAG = ActivityManagerProcessStateTest.class.getName();

    private static final String STUB_PACKAGE_NAME = "android.app.stubs";
    private static final String PACKAGE_NAME_APP1 = "com.android.app1";
    private static final String PACKAGE_NAME_APP2 = "com.android.app2";
    private static final String PACKAGE_NAME_APP3 = "com.android.app3";

    private static final String[] PACKAGE_NAMES = {
            PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, PACKAGE_NAME_APP3
    };

    private static final int WAIT_TIME = 10000;
    private static final int WAITFOR_MSEC = 10000;
    private static final int WAITFOR_ORDERED_BROADCAST_DRAINED = 60000;
    // A secondary test activity from another APK.
    static final String SIMPLE_PACKAGE_NAME = "com.android.cts.launcherapps.simpleapp";
    static final String SIMPLE_SERVICE = ".SimpleService";
    static final String SIMPLE_SERVICE2 = ".SimpleService2";
    static final String SIMPLE_SERVICE3 = ".SimpleService3";
    static final String SIMPLE_RECEIVER_START_SERVICE = ".SimpleReceiverStartService";
    static final String SIMPLE_ACTIVITY_START_SERVICE = ".SimpleActivityStartService";
    static final String SIMPLE_ACTIVITY_START_FG_SERVICE = ".SimpleActivityStartFgService";
    public static String ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT =
            "com.android.cts.launcherapps.simpleapp.SimpleActivityStartService.RESULT";
    static final String ACTION_SIMPLE_ACTIVITY_START_FG =
            "com.android.cts.launcherapps.simpleapp.SimpleActivityStartFgService.START_THEN_FG";
    public static String ACTION_SIMPLE_ACTIVITY_START_FG_SERVICE_RESULT =
            "com.android.cts.launcherapps.simpleapp.SimpleActivityStartFgService.NOW_FOREGROUND";
    public static String ACTION_FINISH_EVERYTHING =
            "com.android.cts.launcherapps.simpleapp.SimpleActivityStartFgService.FINISH_ALL";

    // APKs for testing heavy weight app interactions.
    static final String CANT_SAVE_STATE_1_PACKAGE_NAME = "com.android.test.cantsavestate1";
    static final String CANT_SAVE_STATE_2_PACKAGE_NAME = "com.android.test.cantsavestate2";

    // Actions
    static final String ACTION_START_FOREGROUND = "com.android.test.action.START_FOREGROUND";
    static final String ACTION_STOP_FOREGROUND = "com.android.test.action.STOP_FOREGROUND";
    static final String ACTION_START_THEN_FG = "com.android.test.action.START_THEN_FG";
    static final String ACTION_STOP_SERVICE = "com.android.test.action.STOP";
    static final String ACTION_FINISH = "com.android.test.action.FINISH";

    private static final int TEMP_WHITELIST_DURATION_MS = 2000;

    private Context mContext;
    private Context mTargetContext;
    private Instrumentation mInstrumentation;
    private Intent mServiceIntent;
    private Intent mServiceStartForegroundIntent;
    private Intent mServiceStopForegroundIntent;
    private Intent mService2Intent;
    private Intent mService3Intent;
    private Intent mServiceStartForeground3Intent;
    private Intent mMainProcess[];
    private Intent mAllProcesses[];

    private int mAppCount;
    private ApplicationInfo[] mAppInfo;
    private WatchUidRunner[] mWatchers;

    @Before
    public void setUp() throws Exception {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = mInstrumentation.getContext();
        mTargetContext = mInstrumentation.getTargetContext();
        mServiceIntent = new Intent();
        mServiceIntent.setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE);
        mServiceStartForegroundIntent = new Intent(mServiceIntent);
        mServiceStartForegroundIntent.setAction(ACTION_START_FOREGROUND);
        mServiceStopForegroundIntent = new Intent(mServiceIntent);
        mServiceStopForegroundIntent.setAction(ACTION_STOP_FOREGROUND);
        mService2Intent = new Intent()
                .setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE2);
        mService3Intent = new Intent()
                .setClassName(SIMPLE_PACKAGE_NAME, SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE3);
        mMainProcess = new Intent[1];
        mMainProcess[0] = mServiceIntent;
        mAllProcesses = new Intent[2];
        mAllProcesses[0] = mServiceIntent;
        mAllProcesses[1] = mService2Intent;
        mContext.stopService(mServiceIntent);
        mContext.stopService(mService2Intent);
        mContext.stopService(mService3Intent);
        CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext);
        removeTestAppFromWhitelists();
        mAppCount = 0;
        drainOrderedBroadcastQueue();
        // Make sure we are in Home screen before starting the test
        mInstrumentation.getUiAutomation().performGlobalAction(
                AccessibilityService.GLOBAL_ACTION_HOME);
        // Stop all the packages to avoid residual impact
        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
        for (int i = 0; i < PACKAGE_NAMES.length; i++) {
            final String pkgName = PACKAGE_NAMES[i];
            SystemUtil.runWithShellPermissionIdentity(() -> {
                am.forceStopPackage(pkgName);
            });
        }
    }

    /**
     * Drain the ordered broadcast queue, it'll be useful when the test runs in secondary user
     * which is just created prior to the testing, the ordered broadcast queue could be clogged.
     */
    private void drainOrderedBroadcastQueue() throws Exception {
        final CountDownLatch latch = new CountDownLatch(1);
        final BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                latch.countDown();
            }
        };
        CommandReceiver.sendCommandWithResultReceiver(mContext, CommandReceiver.COMMAND_EMPTY,
                STUB_PACKAGE_NAME, STUB_PACKAGE_NAME, 0, null, receiver);
        latch.await(WAITFOR_ORDERED_BROADCAST_DRAINED, TimeUnit.MILLISECONDS);
        Log.i(TAG, "Ordered broadcast queue drained");
    }

    /**
     * Set up count app info objects and WatchUidRunners.
     */
    private void setupWatchers(int count) throws Exception {
        mAppCount = count;
        mAppInfo = new ApplicationInfo[count];
        mWatchers = new WatchUidRunner[count];
        for (int i = 0; i < count; i++) {
            mAppInfo[i] = mContext.getPackageManager().getApplicationInfo(
                    PACKAGE_NAMES[i], 0);
            mWatchers[i] = new WatchUidRunner(mInstrumentation, mAppInfo[i].uid,
                    WAITFOR_MSEC);
        }
    }

    /**
     * Finish all started WatchUidRunners.
     */
    private void shutdownWatchers() throws Exception {
        for (int i = 0; i < mAppCount; i++) {
            mWatchers[i].finish();
        }
    }

    private void removeTestAppFromWhitelists() throws Exception {
        CtsAppTestUtils.executeShellCmd(mInstrumentation,
                "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME);
        CtsAppTestUtils.executeShellCmd(mInstrumentation,
                "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
    }

    private void waitForAppFocus(String waitForApp, long waitTime) {
        long waitUntil = SystemClock.elapsedRealtime() + waitTime;
        while (true) {
            WindowManagerState wms = new WindowManagerState();
            wms.computeState();
            String appName = wms.getFocusedApp();
            if (appName != null) {
                ComponentName comp = ComponentName.unflattenFromString(appName);
                if (waitForApp.equals(comp.getPackageName())) {
                    break;
                }
            }
            if (SystemClock.elapsedRealtime() > waitUntil) {
                throw new IllegalStateException("Timed out waiting for focus on app "
                        + waitForApp + ", last was " + appName);
            }
            Log.i(TAG, "Waiting for app focus, current: " + appName);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
    }

    private void startActivityAndWaitForShow(final Intent intent) throws Exception {
        mInstrumentation.getUiAutomation().executeAndWaitForEvent(
                () -> {
                    try {
                        mTargetContext.startActivity(intent);
                    } catch (Exception e) {
                        fail("Cannot start activity: " + intent);
                    }
                }, (AccessibilityEvent event) -> event.getEventType()
                        == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                , WAIT_TIME);
    }

    private void maybeClick(UiDevice device, UiSelector sel) {
        try {
            device.findObject(sel).click();
        } catch (Throwable ignored) {
        }
    }

    private void maybeClick(UiDevice device, BySelector sel) {
        try {
            device.findObject(sel).click();
        } catch (Throwable ignored) {
        }
    }

    /**
     * Test basic state changes as processes go up and down due to services running in them.
     */
    @Test
    public void testUidImportanceListener() throws Exception {
        final Parcel data = Parcel.obtain();
        ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent,
                WAIT_TIME);
        ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent,
                WAIT_TIME);

        ActivityManager am = mContext.getSystemService(ActivityManager.class);

        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                SIMPLE_PACKAGE_NAME, 0);
        UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);

        PermissionUtils.revokePermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        boolean gotException = false;
        try {
            uidForegroundListener.register();
        } catch (SecurityException e) {
            gotException = true;
        }
        assertTrue("Expected SecurityException thrown", gotException);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        /*
        Log.d("XXXX", "Invoke: " + cmd);
        Log.d("XXXX", "Result: " + result);
        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                + STUB_PACKAGE_NAME));
        */
        uidForegroundListener.register();

        UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
                appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
        uidGoneListener.register();

        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                WAIT_TIME);

        try {
            // First kill the processes to start out in a stable state.
            conn.bind();
            conn2.bind();
            IBinder service1 = conn.getServiceIBinder();
            IBinder service2 = conn2.getServiceIBinder();
            conn.unbind();
            conn2.unbind();
            try {
                service1.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
            } catch (RemoteException e) {
            }
            try {
                service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
            } catch (RemoteException e) {
            }
            service1 = service2 = null;

            // Wait for uid's processes to go away.
            uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE);
            assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // And wait for the uid report to be gone.
            uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);

            // Now bind and see if we get told about the uid coming in to the foreground.
            conn.bind();
            uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE);
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // Also make sure the uid state reports are as expected.  Wait for active because
            // there may be some intermediate states as the process comes up.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Pull out the service IBinder for a kludy hack...
            IBinder service = conn.getServiceIBinder();

            // Now unbind and see if we get told about it going to the background.
            conn.unbind();
            uidForegroundListener.waitForValue(IMPORTANCE_CACHED, IMPORTANCE_CACHED);
            assertEquals(IMPORTANCE_CACHED, am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Now kill the process and see if we are told about it being gone.
            try {
                service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
            } catch (RemoteException e) {
                // It is okay if it is already gone for some reason.
            }

            uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE);
            assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
            uidWatcher.expect(WatchUidRunner.CMD_GONE, null);

            // Now we are going to try different combinations of binding to two processes to
            // see if they are correctly combined together for the app.

            // Bring up both services.
            conn.bind();
            conn2.bind();
            uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE);
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Bring down one service, app state should remain foreground.
            conn2.unbind();
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // Bring down other service, app state should now be cached.  (If the processes both
            // actually get killed immediately, this is also not a correctly behaving system.)
            conn.unbind();
            uidGoneListener.waitForValue(IMPORTANCE_CACHED, IMPORTANCE_CACHED);
            assertEquals(IMPORTANCE_CACHED,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Bring up one service, this should be sufficient to become foreground.
            conn2.bind();
            uidForegroundListener.waitForValue(IMPORTANCE_FOREGROUND, IMPORTANCE_VISIBLE);
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Bring up other service, should remain foreground.
            conn.bind();
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // Bring down one service, should remain foreground.
            conn.unbind();
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // And bringing down other service should put us back to cached.
            conn2.unbind();
            uidGoneListener.waitForValue(IMPORTANCE_CACHED,
                    IMPORTANCE_CACHED);
            assertEquals(IMPORTANCE_CACHED,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
        } finally {
            data.recycle();
            uidWatcher.finish();
            uidForegroundListener.unregister();
            uidGoneListener.unregister();
        }
    }

    /**
     * Test that background check correctly prevents idle services from running but allows
     * whitelisted apps to bypass the check.
     */
    @Test
    public void testBackgroundCheckService() throws Exception {
        final Parcel data = Parcel.obtain();
        Intent serviceIntent = new Intent();
        serviceIntent.setClassName(SIMPLE_PACKAGE_NAME,
                SIMPLE_PACKAGE_NAME + SIMPLE_SERVICE);
        ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, serviceIntent,
                WAIT_TIME);

        ActivityManager am = mContext.getSystemService(ActivityManager.class);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        /*
        Log.d("XXXX", "Invoke: " + cmd);
        Log.d("XXXX", "Result: " + result);
        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                + STUB_PACKAGE_NAME));
        */

        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                SIMPLE_PACKAGE_NAME, 0);

        UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
        uidForegroundListener.register();
        UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY, WAIT_TIME);
        uidGoneListener.register();

        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                WAIT_TIME);

        final int userId = UserHandle.getUserId(appInfo.uid);

        // First kill the process to start out in a stable state.
        mContext.stopService(serviceIntent);
        conn.bind();
        IBinder service = conn.getServiceIBinder();
        conn.unbind();
        try {
            service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
        } catch (RemoteException e) {
        }
        service = null;

        // Wait for uid's process to go away.
        uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE);
        assertEquals(IMPORTANCE_GONE,
                am.getPackageImportance(SIMPLE_PACKAGE_NAME));

        // And wait for the uid report to be gone.
        uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);

        String cmd = "appops set --user " + userId + " "
                + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // This is a side-effect of the app op command.
        uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
        uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, "NONE");

        // We don't want to wait for the uid to actually go idle, we can force it now.
        cmd = "am make-uid-idle --user " + userId + " " + SIMPLE_PACKAGE_NAME;
        result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // Make sure app is not yet on whitelist
        cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
        result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // We will use this to monitor when the service is running.
        conn.startMonitoring();

        try {
            // Try starting the service.  Should fail!
            boolean failed = false;
            try {
                mContext.startService(serviceIntent);
            } catch (IllegalStateException e) {
                failed = true;
            }
            if (!failed) {
                fail("Service was allowed to start while in the background");
            }

            // Put app on temporary whitelist to see if this allows the service start.
            cmd = String.format("cmd deviceidle tempwhitelist -u %d -d %d %s",
                    userId, TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            // Try starting the service now that the app is whitelisted...  should work!
            mContext.startService(serviceIntent);
            conn.waitForConnect();

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Good, now stop the service and give enough time to get off the temp whitelist.
            mContext.stopService(serviceIntent);
            conn.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            CtsAppTestUtils.executeShellCmd(mInstrumentation,
                    "cmd deviceidle tempwhitelist -u " + userId + " -r " + SIMPLE_PACKAGE_NAME);

            // Going off the temp whitelist causes a spurious proc state report...  that's
            // not ideal, but okay.
            // uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // We don't want to wait for the uid to actually go idle, we can force it now.
            cmd = "am make-uid-idle --user " + userId + " " + SIMPLE_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Now that we should be off the temp whitelist, make sure we again can't start.
            failed = false;
            try {
                mContext.startService(serviceIntent);
            } catch (IllegalStateException e) {
                failed = true;
            }
            if (!failed) {
                fail("Service was allowed to start while in the background");
            }

            // Now put app on whitelist, should allow service to run.
            cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            // Try starting the service now that the app is whitelisted...  should work!
            mContext.startService(serviceIntent);
            conn.waitForConnect();

            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Okay, bring down the service.
            mContext.stopService(serviceIntent);
            conn.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

        } finally {
            mContext.stopService(serviceIntent);
            conn.stopMonitoring();

            uidWatcher.finish();

            cmd = "appops set --user " + userId + " "
                    + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            uidGoneListener.unregister();
            uidForegroundListener.unregister();

            data.recycle();
        }
    }

    /**
     * Test that background check behaves correctly after a process is no longer foreground: first
     * allowing a service to be started, then stopped by the system when idle.
     */
    @Test
    public void testBackgroundCheckStopsService() throws Exception {
        final Parcel data = Parcel.obtain();
        ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext, mServiceIntent,
                WAIT_TIME);
        ServiceConnectionHandler conn2 = new ServiceConnectionHandler(mContext, mService2Intent,
                WAIT_TIME);

        ActivityManager am = mContext.getSystemService(ActivityManager.class);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        /*
        Log.d("XXXX", "Invoke: " + cmd);
        Log.d("XXXX", "Result: " + result);
        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                + STUB_PACKAGE_NAME));
        */

        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                SIMPLE_PACKAGE_NAME, 0);

        UidImportanceListener uidServiceListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
        uidServiceListener.register();
        UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
                appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
        uidGoneListener.register();

        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                WAIT_TIME);

        // First kill the process to start out in a stable state.
        mContext.stopService(mServiceIntent);
        mContext.stopService(mService2Intent);
        conn.bind();
        conn2.bind();
        IBinder service = conn.getServiceIBinder();
        IBinder service2 = conn2.getServiceIBinder();
        conn.unbind();
        conn2.unbind();
        try {
            service.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
        } catch (RemoteException e) {
        }
        try {
            service2.transact(IBinder.FIRST_CALL_TRANSACTION, data, null, 0);
        } catch (RemoteException e) {
        }
        service = service2 = null;

        // Wait for uid's process to go away.
        uidGoneListener.waitForValue(IMPORTANCE_GONE,
                IMPORTANCE_GONE);
        assertEquals(IMPORTANCE_GONE,
                am.getPackageImportance(SIMPLE_PACKAGE_NAME));

        // And wait for the uid report to be gone.
        uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, WAIT_TIME);

        String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // This is a side-effect of the app op command.
        uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
        uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_NONEXISTENT);

        // We don't want to wait for the uid to actually go idle, we can force it now.
        cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
        result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // Make sure app is not yet on whitelist
        cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
        result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        // We will use this to monitor when the service is running.
        conn.startMonitoring();

        try {
            // Try starting the service.  Should fail!
            boolean failed = false;
            try {
                mContext.startService(mServiceIntent);
            } catch (IllegalStateException e) {
                failed = true;
            }
            if (!failed) {
                fail("Service was allowed to start while in the background");
            }

            // First poke the process into the foreground, so we can avoid background check.
            conn2.bind();
            conn2.waitForConnect();

            // Wait for process state to reflect running service.
            uidServiceListener.waitForValue(
                    IMPORTANCE_FOREGROUND_SERVICE,
                    ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE);
            assertEquals(IMPORTANCE_FOREGROUND_SERVICE,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            conn2.unbind();

            // Wait for process to recover back down to being cached.
            uidServiceListener.waitForValue(IMPORTANCE_CACHED,
                    IMPORTANCE_GONE);
            assertEquals(IMPORTANCE_CACHED,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Try starting the service now that the app is waiting to idle...  should work!
            mContext.startService(mServiceIntent);
            conn.waitForConnect();

            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // And also start the second service.
            conn2.startMonitoring();
            mContext.startService(mService2Intent);
            conn2.waitForConnect();

            // Force app to go idle now
            cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            // Wait for services to be stopped by system.
            uidServiceListener.waitForValue(IMPORTANCE_CACHED,
                    IMPORTANCE_GONE);
            assertEquals(IMPORTANCE_CACHED,
                    am.getPackageImportance(SIMPLE_PACKAGE_NAME));

            // And service should be stopped by system, so just make sure it is disconnected.
            conn.waitForDisconnect();
            conn2.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
            // There may be a transient 'SVC' proc state here.
            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

        } finally {
            mContext.stopService(mServiceIntent);
            mContext.stopService(mService2Intent);
            conn.cleanup();
            conn2.cleanup();

            uidWatcher.finish();

            cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

            uidGoneListener.unregister();
            uidServiceListener.unregister();

            data.recycle();
        }
    }

    /**
     * Test the background check doesn't allow services to be started from broadcasts except when in
     * the correct states.
     */
    @Test
    public void testBackgroundCheckBroadcastService() throws Exception {
        final Intent broadcastIntent = new Intent();
        broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        broadcastIntent.setClassName(SIMPLE_PACKAGE_NAME,
                SIMPLE_PACKAGE_NAME + SIMPLE_RECEIVER_START_SERVICE);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        final ServiceProcessController controller = new ServiceProcessController(mContext,
                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
        final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                mServiceIntent, WAIT_TIME);
        final WatchUidRunner uidWatcher = controller.getUidWatcher();

        try {
            // First kill the process to start out in a stable state.
            controller.ensureProcessGone();

            // Do initial setup.
            controller.denyBackgroundOp();
            controller.makeUidIdle();
            controller.removeFromWhitelist();

            // We will use this to monitor when the service is running.
            conn.startMonitoring();

            // Try sending broadcast to start the service.  Should fail!
            SyncOrderedBroadcast br = new SyncOrderedBroadcast();
            broadcastIntent.putExtra("service", mServiceIntent);
            br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
            int brCode = br.getReceivedCode();
            if (brCode != Activity.RESULT_CANCELED) {
                fail("Didn't fail starting service, result=" + brCode);
            }

            // Track the uid proc state changes from the broadcast (but not service execution)
            uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null, WAIT_TIME);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null, WAIT_TIME);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER,
                    WAIT_TIME);
            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null, WAIT_TIME);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
                    WAIT_TIME);

            // Put app on temporary whitelist to see if this allows the service start.
            controller.tempWhitelist(TEMP_WHITELIST_DURATION_MS);

            // Being on the whitelist means the uid is now active.
            uidWatcher.expect(WatchUidRunner.CMD_ACTIVE, null, WAIT_TIME);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
                    WAIT_TIME);

            // Try starting the service now that the app is whitelisted...  should work!
            br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
            brCode = br.getReceivedCode();
            if (brCode != Activity.RESULT_FIRST_USER) {
                fail("Failed starting service, result=" + brCode);
            }
            conn.waitForConnect();

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            // We are going to wait until 'SVC', because we may see an intermediate 'RCVR'
            // proc state depending on timing.
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Good, now stop the service and give enough time to get off the temp whitelist.
            mContext.stopService(mServiceIntent);
            conn.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            controller.removeFromTempWhitelist();

            // Going off the temp whitelist causes a spurious proc state report...  that's
            // not ideal, but okay.
            // uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // We don't want to wait for the uid to actually go idle, we can force it now.
            controller.makeUidIdle();

            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);

            // Make sure the process is gone so we start over fresh.
            controller.ensureProcessGone();

            // Now that we should be off the temp whitelist, make sure we again can't start.
            br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
            brCode = br.getReceivedCode();
            if (brCode != Activity.RESULT_CANCELED) {
                fail("Didn't fail starting service, result=" + brCode);
            }

            // Track the uid proc state changes from the broadcast (but not service execution)
            uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null);
            // There could be a transient 'cached' state here before 'uncached' if uid state
            // changes are dispatched before receiver is started.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_RECEIVER);
            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Now put app on whitelist, should allow service to run.
            controller.addToWhitelist();

            // Try starting the service now that the app is whitelisted...  should work!
            br.sendAndWait(mContext, broadcastIntent, Activity.RESULT_OK, null, null, WAIT_TIME);
            brCode = br.getReceivedCode();
            if (brCode != Activity.RESULT_FIRST_USER) {
                fail("Failed starting service, result=" + brCode);
            }
            conn.waitForConnect();

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Okay, bring down the service.
            mContext.stopService(mServiceIntent);
            conn.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

        } finally {
            mContext.stopService(mServiceIntent);
            conn.stopMonitoringIfNeeded();
            controller.cleanup();
        }
    }

    /**
     * Test that background check does allow services to be started from activities.
     */
    @Test
    public void testBackgroundCheckActivityService() throws Exception {
        final Intent activityIntent = new Intent();
        activityIntent.setClassName(SIMPLE_PACKAGE_NAME,
                SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_START_SERVICE);
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        final ServiceProcessController controller = new ServiceProcessController(mContext,
                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
        final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                mServiceIntent, WAIT_TIME);
        final WatchUidRunner uidWatcher = controller.getUidWatcher();

        try {
            // First kill the process to start out in a stable state.
            controller.ensureProcessGone();

            // Do initial setup.
            controller.denyBackgroundOp();
            controller.makeUidIdle();
            controller.removeFromWhitelist();

            // We will use this to monitor when the service is running.
            conn.startMonitoring();

            // Try starting activity that will start the service.  This should be okay.
            WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
            waiter.prepare(ACTION_SIMPLE_ACTIVITY_START_SERVICE_RESULT);
            activityIntent.putExtra("service", mServiceIntent);
            mTargetContext.startActivity(activityIntent);
            Intent resultIntent = waiter.doWait(WAIT_TIME * 2);
            int brCode = resultIntent.getIntExtra("result", Activity.RESULT_CANCELED);
            if (brCode != Activity.RESULT_FIRST_USER) {
                fail("Failed starting service, result=" + brCode);
            }
            conn.waitForConnect();

            final String expectedActivityState = (CtsAppTestUtils.isScreenInteractive(mContext)
                    && !CtsAppTestUtils.isKeyguardLocked(mContext))
                    ? WatchUidRunner.STATE_TOP : WatchUidRunner.STATE_TOP_SLEEPING;
            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, expectedActivityState);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Okay, bring down the service.
            mContext.stopService(mServiceIntent);
            conn.waitForDisconnect();

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // App isn't yet idle, so we should be able to start the service again.
            mContext.startService(mServiceIntent);
            conn.waitForConnect();
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // And now fast-forward to the app going idle, service should be stopped.
            controller.makeUidIdle();
            uidWatcher.waitFor(WatchUidRunner.CMD_IDLE, null);

            conn.waitForDisconnect();
            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // No longer should be able to start service.
            boolean failed = false;
            try {
                mContext.startService(mServiceIntent);
            } catch (IllegalStateException e) {
                failed = true;
            }
            if (!failed) {
                fail("Service was allowed to start while in the background");
            }

        } finally {
            mContext.stopService(mServiceIntent);
            conn.stopMonitoringIfNeeded();
            controller.cleanup();
        }
    }

    /**
     * Test that the foreground service app op does prevent the foreground state.
     */
    @Test
    public void testForegroundServiceAppOp() throws Exception {
        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        // Use default timeout value 5000
        final ServiceProcessController controller = new ServiceProcessController(mContext,
                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses);
        // Use default timeout value 5000
        final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                mServiceIntent);
        final WatchUidRunner uidWatcher = controller.getUidWatcher();

        try {
            // First kill the process to start out in a stable state.
            controller.ensureProcessGone();

            // Do initial setup.
            controller.makeUidIdle();
            controller.removeFromWhitelist();
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");

            // Put app on whitelist, to allow service to run.
            controller.addToWhitelist();

            // We will use this to monitor when the service is running.
            conn.startMonitoring();

            // -------- START SERVICE AND THEN SUCCESSFULLY GO TO FOREGROUND

            // Now start the service and wait for it to come up.
            mContext.startService(mServiceStartForegroundIntent);
            conn.waitForConnect();

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Now take it out of foreground and confirm.
            mContext.startService(mServiceStopForegroundIntent);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Good, now stop the service and wait for it to go away.
            mContext.stopService(mServiceStartForegroundIntent);
            conn.waitForDisconnect();

            // There may be a transient STATE_SERVICE we don't care about, so waitFor.
            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // We don't want to wait for the uid to actually go idle, we can force it now.
            controller.makeUidIdle();
            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);

            // Make sure the process is gone so we start over fresh.
            controller.ensureProcessGone();

            // -------- START SERVICE AND BLOCK GOING TO FOREGROUND

            // Now we will deny the app op and ensure the service can't become foreground.
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");

            // Now start the service and wait for it to come up.
            mContext.startService(mServiceStartForegroundIntent);
            conn.waitForConnect();

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Good, now stop the service and wait for it to go away.
            mContext.stopService(mServiceStartForegroundIntent);
            conn.waitForDisconnect();

            // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE.
            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Make sure the uid is idle (it should be anyway, it never went active here).
            controller.makeUidIdle();

            // Make sure the process is gone so we start over fresh.
            controller.ensureProcessGone();

            // -------- DIRECT START FOREGROUND SERVICE SUCCESSFULLY

            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");

            // Now start the service and wait for it to come up.
            mContext.startForegroundService(mServiceStartForegroundIntent);
            conn.waitForConnect();

            // Make sure it becomes a foreground service.  The process state changes here
            // are weird looking because we first need to force the app out of idle to allow
            // it to start the service.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
            // Remove tempwhitelist avoid temp white list block idle command and app crash occur.
            CtsAppTestUtils.executeShellCmd(mInstrumentation,
                    "cmd deviceidle tempwhitelist -r " + SIMPLE_PACKAGE_NAME);
            // Good, now stop the service and wait for it to go away.
            mContext.stopService(mServiceStartForegroundIntent);
            conn.waitForDisconnect();

            // There may be a transient STATE_SERVICE we don't care about, so waitFor.
            uidWatcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // We don't want to wait for the uid to actually go idle, we can force it now.
            controller.makeUidIdle();

            // Make sure the process is gone so we start over fresh.
            controller.ensureProcessGone();

            // -------- DIRECT START FOREGROUND SERVICE BLOCKED

            // Now we will deny the app op and ensure the service can't become foreground.
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");

            // But we will put it on the whitelist so the service is still allowed to start.
            controller.addToWhitelist();

            // Now start the service and wait for it to come up.
            mContext.startForegroundService(mServiceStartForegroundIntent);
            conn.waitForConnect();

            // In this case we only get to run it as a regular service.
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);

            // Good, now stop the service and wait for it to go away.
            mContext.stopService(mServiceStartForegroundIntent);
            conn.waitForDisconnect();

            // THIS MUST BE AN EXPECT: we want to make sure we don't get in to STATE_FG_SERVICE.
            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);

            // Make sure the uid is idle (it should be anyway, it never went active here).
            controller.makeUidIdle();

            // Make sure the process is gone so we start over fresh.
            controller.ensureProcessGone();

            // -------- XXX NEED TO TEST NON-WHITELIST CASE WHERE NOTHING HAPPENS

        } finally {
            mContext.stopService(mServiceStartForegroundIntent);
            conn.stopMonitoringIfNeeded();
            controller.cleanup();
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");
            controller.removeFromWhitelist();
        }
    }

    /**
     * Verify that an app under background restrictions has its foreground services demoted to
     * ordinary service state when it is no longer the top app.
     */
    @Test
    public void testBgRestrictedForegroundService() throws Exception {
        final Intent activityIntent = new Intent()
                .setClassName(SIMPLE_PACKAGE_NAME,
                        SIMPLE_PACKAGE_NAME + SIMPLE_ACTIVITY_START_FG_SERVICE)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        final ServiceProcessController controller = new ServiceProcessController(mContext,
                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
        final WatchUidRunner uidWatcher = controller.getUidWatcher();

        final Intent homeIntent = new Intent()
                .setAction(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_HOME)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

        final Intent serviceStartIntent = new Intent(mService3Intent)
                .setAction(ACTION_START_THEN_FG);
        activityIntent.putExtra("service", serviceStartIntent);
        boolean activityStarted = false;

        try {
            // First kill the process to start out in a stable state.
            controller.ensureProcessGone();

            // Do initial setup.
            controller.denyAnyInBackgroundOp();
            controller.makeUidIdle();
            controller.removeFromWhitelist();
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");

            // Start the activity, which will start the fg service as well, and wait
            // for the report that it's all up and running.
            WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
            waiter.prepare(ACTION_SIMPLE_ACTIVITY_START_FG_SERVICE_RESULT);

            activityIntent.setAction(ACTION_SIMPLE_ACTIVITY_START_FG);
            mTargetContext.startActivity(activityIntent);
            activityStarted = true;

            Intent resultIntent = waiter.doWait(WAIT_TIME);
            int brCode = resultIntent.getIntExtra("result", Activity.RESULT_CANCELED);
            if (brCode != Activity.RESULT_FIRST_USER) {
                fail("Failed starting service, result=" + brCode);
            }

            // activity is in front, fg service is running.  make sure that we see
            // the expected state at this point.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Switch to the home app; make sure the test app drops all the way
            // down to SERVICE, not FG_SERVICE
            mTargetContext.startActivity(homeIntent);
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_SERVICE);
        } finally {
            // tear down everything and we're done
            if (activityStarted) {
                activityIntent.setAction(ACTION_FINISH_EVERYTHING);
                mTargetContext.startActivity(activityIntent);
            }

            controller.cleanup();
        }

    }

    private boolean supportsCantSaveState() {
        if (mContext.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CANT_SAVE_STATE)) {
            return true;
        }

        return false;
    }

    /**
     * Test that a single "can't save state" app has the proper process management semantics.
     */
    @Test
    public void testCantSaveStateLaunchAndBackground() throws Exception {
        if (!supportsCantSaveState()) {
            return;
        }

        final Intent activityIntent = new Intent();
        activityIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
        activityIntent.setAction(Intent.ACTION_MAIN);
        activityIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        final Intent homeIntent = new Intent();
        homeIntent.setAction(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ActivityManager am = mContext.getSystemService(ActivityManager.class);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);

        // We don't want to wait for the uid to actually go idle, we can force it now.
        String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                CANT_SAVE_STATE_1_PACKAGE_NAME, 0);

        // This test is also using UidImportanceListener to make sure the correct
        // heavy-weight state is reported there.
        UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
                appInfo.uid, IMPORTANCE_FOREGROUND,
                WAIT_TIME);
        uidForegroundListener.register();
        UidImportanceListener uidBackgroundListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE - 1,
                WAIT_TIME);
        uidBackgroundListener.register();
        UidImportanceListener uidCachedListener = new UidImportanceListener(mContext,
                appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE + 1,
                WAIT_TIME);
        uidCachedListener.register();

        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                WAIT_TIME);

        UiDevice device = UiDevice.getInstance(mInstrumentation);

        try {
            // Start the heavy-weight app, should launch like a normal app.
            mTargetContext.startActivity(activityIntent);
            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // Wait for process state to reflect running activity.
            uidForegroundListener.waitForValue(
                    IMPORTANCE_FOREGROUND,
                    IMPORTANCE_FOREGROUND);
            assertEquals(IMPORTANCE_FOREGROUND,
                    am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Now go to home, leaving the app.  It should be put in the heavy weight state.
            mTargetContext.startActivity(homeIntent);

            final int expectedImportance =
                    (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O)
                            ? ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE
                            : ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE_PRE_26;
            // Wait for process to go down to background heavy-weight.
            uidBackgroundListener.waitForValue(expectedImportance, expectedImportance);
            assertEquals(expectedImportance,
                    am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);

            // While in background, should go in to normal idle state.
            // Force app to go idle now
            cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);

            // Switch back to heavy-weight app to see if it correctly returns to foreground.
            mTargetContext.startActivity(activityIntent);

            // Wait for process state to reflect running activity.
            uidForegroundListener.waitForValue(
                    IMPORTANCE_FOREGROUND,
                    IMPORTANCE_FOREGROUND);
            assertEquals(IMPORTANCE_FOREGROUND,
                    am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));

            // Also make sure the uid state reports are as expected.
            uidWatcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // Exit activity, check to see if we are now cached.
            final Intent finishIntent = new Intent();
            finishIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
            finishIntent.setAction(ACTION_FINISH);
            finishIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            finishIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            mTargetContext.startActivity(finishIntent);

            // Wait for process to become cached
            uidCachedListener.waitForValue(
                    IMPORTANCE_CACHED,
                    IMPORTANCE_CACHED);
            assertEquals(IMPORTANCE_CACHED,
                    am.getPackageImportance(CANT_SAVE_STATE_1_PACKAGE_NAME));

            uidWatcher.expect(WatchUidRunner.CMD_CACHED, null);
            uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);

            // While in background, should go in to normal idle state.
            // Force app to go idle now
            cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);

        } finally {
            uidWatcher.finish();
            uidForegroundListener.unregister();
            uidBackgroundListener.unregister();
            uidCachedListener.unregister();
        }
    }

    /**
     * Test that switching between two "can't save state" apps is handled properly.
     */
    @Test
    public void testCantSaveStateLaunchAndSwitch() throws Exception {
        if (!supportsCantSaveState()) {
            return;
        }

        final Intent activity1Intent = new Intent();
        activity1Intent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
        activity1Intent.setAction(Intent.ACTION_MAIN);
        activity1Intent.addCategory(Intent.CATEGORY_LAUNCHER);
        activity1Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        final Intent activity2Intent = new Intent();
        activity2Intent.setPackage(CANT_SAVE_STATE_2_PACKAGE_NAME);
        activity2Intent.setAction(Intent.ACTION_MAIN);
        activity2Intent.addCategory(Intent.CATEGORY_LAUNCHER);
        activity2Intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        final Intent homeIntent = new Intent();
        homeIntent.setAction(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        ActivityManager am = mContext.getSystemService(ActivityManager.class);
        UiDevice device = UiDevice.getInstance(mInstrumentation);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);

        // We don't want to wait for the uid to actually go idle, we can force it now.
        String cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
        cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
        result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAIT_TIME);

        ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
                CANT_SAVE_STATE_2_PACKAGE_NAME, 0);
        WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
                WAIT_TIME);

        try {
            // Start the first heavy-weight app, should launch like a normal app.
            mTargetContext.startActivity(activity1Intent);
            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // Make sure the uid state reports are as expected.
            uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Now go to home, leaving the app.  It should be put in the heavy weight state.
            mTargetContext.startActivity(homeIntent);

            // Wait for process to go down to background heavy-weight.
            uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);

            // Start the second heavy-weight app, should ask us what to do with the two apps
            startActivityAndWaitForShow(activity2Intent);

            // First, let's try returning to the original app.
            maybeClick(device, new UiSelector().resourceId("android:id/switch_old"));
            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // App should now be back in foreground.
            uid1Watcher.expect(WatchUidRunner.CMD_UNCACHED, null);
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Return to home.
            mTargetContext.startActivity(homeIntent);
            uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);

            // Again try starting second heavy-weight app to get prompt.
            startActivityAndWaitForShow(activity2Intent);

            // Now we'll switch to the new app.
            maybeClick(device, new UiSelector().resourceId("android:id/switch_new"));
            waitForAppFocus(CANT_SAVE_STATE_2_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // The original app should now become cached.
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);

            // And the new app should start.
            uid2Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Make sure the original app is idle for cleanliness
            cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            uid1Watcher.expect(WatchUidRunner.CMD_IDLE, null);

            // Return to home.
            mTargetContext.startActivity(homeIntent);
            uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);

            // Try starting the first heavy weight app, but return to the existing second.
            startActivityAndWaitForShow(activity1Intent);
            maybeClick(device, new UiSelector().resourceId("android:id/switch_old"));
            waitForAppFocus(CANT_SAVE_STATE_2_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();
            uid2Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            // Return to home.
            mTargetContext.startActivity(homeIntent);
            uid2Watcher.waitFor(WatchUidRunner.CMD_CACHED, null);
            uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_HEAVY_WEIGHT);

            // Again start the first heavy weight app, this time actually switching to it
            startActivityAndWaitForShow(activity1Intent);
            maybeClick(device, new UiSelector().resourceId("android:id/switch_new"));
            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // The second app should now become cached.
            uid2Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);

            // And the first app should start.
            uid1Watcher.waitFor(WatchUidRunner.CMD_ACTIVE, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_UNCACHED, null);
            uid1Watcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP);

            waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
            device.waitForIdle();

            // Exit activity, check to see if we are now cached.
            final Intent finishIntent = new Intent();
            finishIntent.setPackage(CANT_SAVE_STATE_1_PACKAGE_NAME);
            finishIntent.setAction(ACTION_FINISH);
            finishIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            finishIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
            mTargetContext.startActivity(finishIntent);

            uid1Watcher.expect(WatchUidRunner.CMD_CACHED, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT);

            // Make both apps idle for cleanliness.
            cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
            cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
            result = SystemUtil.runShellCommand(mInstrumentation, cmd);

        } finally {
            uid2Watcher.finish();
            uid1Watcher.finish();
        }
    }

    /**
     * Test a service binding cycle between two apps, with one of them also running a foreground
     * service. The other app should also get an FGS proc state. On stopping the foreground service,
     * app should go back to cached state.
     *
     * @throws Exception
     */
    @Test
    public void testCycleFgs() throws Exception {
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP3, 0);
        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
                WAITFOR_MSEC);

        try {
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);

            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Create a cycle
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            try {
                uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                        WatchUidRunner.STATE_CACHED_EMPTY);
                fail("App3 should not be demoted to cached");
            } catch (IllegalStateException ise) {
                // Didn't go to cached in spite of cycle. Good!
            }

            // Stop the foreground service
            CommandReceiver.sendCommand(mContext, CommandReceiver
                            .COMMAND_STOP_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);

            // Check that the app's proc state has fallen
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);

            uid1Watcher.finish();
            uid3Watcher.finish();
        }
    }

    /**
     * Test a service binding cycle between three apps, with one of them also running a foreground
     * service. The other apps should also get an FGS proc state. On stopping the foreground
     * service, app should go back to cached state.
     *
     * @throws Exception
     */
    @Test
    public void testCycleFgsTriangle() throws Exception {
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP2, 0);
        ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP3, 0);
        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
                WAITFOR_MSEC);

        try {
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);

            uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Bind from 2 to 3
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Create a cycle
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            try {
                uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                        WatchUidRunner.STATE_CACHED_EMPTY);
                fail("App3 should not be demoted to cached");
            } catch (IllegalStateException ise) {
                // Didn't go to cached in spite of cycle. Good!
            }

            try {
                uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                        WatchUidRunner.STATE_CACHED_EMPTY);
                fail("App2 should not be demoted to cached");
            } catch (IllegalStateException ise) {
                // Didn't go to cached in spite of cycle. Good!
            }

            try {
                uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                        WatchUidRunner.STATE_CACHED_EMPTY);
                fail("App1 should not be demoted to cached");
            } catch (IllegalStateException ise) {
                // Didn't go to cached in spite of cycle. Good!
            }

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);

            uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);
            // Stop the foreground service
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);

            uid1Watcher.finish();
            uid2Watcher.finish();
            uid3Watcher.finish();
        }
    }

    /**
     * Test a service binding cycle between three apps, with one of them also running a foreground
     * service. The other apps should also get an FGS proc state. On stopping the foreground
     * service, app should go back to cached state.
     *
     * @throws Exception
     */
    @Test
    public void testCycleFgsTriangleBiDi() throws Exception {
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP2, 0);
        ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP3, 0);
        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
                WAITFOR_MSEC);

        try {
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Bind from 1 to 2, 1 to 3
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);

            uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);

            // Bind from 2 to 3, 3 to 2, 3 to 1
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            try {
                uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                        WatchUidRunner.STATE_CACHED_EMPTY);
                fail("App3 should not be demoted to cached");
            } catch (IllegalStateException ise) {
                // Didn't go to cached in spite of cycle. Good!
            }

            // Stop the foreground service
            CommandReceiver.sendCommand(mContext, CommandReceiver
                            .COMMAND_STOP_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);

            // Check that the apps' proc state has fallen
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP2, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            uid1Watcher.finish();
            uid2Watcher.finish();
            uid3Watcher.finish();
        }
    }

    /**
     * Test process states for foreground service binding to another app, with and without
     * BIND_INCLUDE_CAPABILITIES. With BIND_INCLUDE_CAPABILITIES flag,
     * PROCESS_CAPABILITY_FOREGROUND_LOCATION can be passed from client to service. Without
     * BIND_INCLUDE_CAPABILITIES flag, PROCESS_CAPABILITY_FOREGROUND_LOCATION can not be passed from
     * client to service.
     * @throws Exception
     */
    @Test
    public void testFgsLocationBind() throws Exception {
        setupWatchers(3);

        try {
            // Put Package1 in TOP state, now it gets all capability (because the TOP process
            // gets all while-in-use permission (not from FGSL).
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_ACTIVITY,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_TOP,
                    new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION
                            | PROCESS_CAPABILITY_ALL));

            // Start a FGS
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null);

            // Start a FGSL
            Bundle bundle = new Bundle();
            bundle.putInt(LocalForegroundServiceLocation.EXTRA_FOREGROUND_SERVICE_TYPE,
                    ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION);
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
                    mAppInfo[0].packageName, mAppInfo[0].packageName, 0, bundle);

            // Stop the activity.
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_STOP_ACTIVITY,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);

            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_FG_SERVICE,
                    new Integer(PROCESS_CAPABILITY_NETWORK | PROCESS_CAPABILITY_FOREGROUND_LOCATION
                            | PROCESS_CAPABILITY_ALL_IMPLICIT));

            // Bind App 0 -> App 1, verify doesn't include capability.
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[1].packageName, 0, null);
            // Verify app1 does NOT have capability.
            mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_FG_SERVICE,
                    new Integer(PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK));

            // Bind App 0 -> App 2, include capability.
            bundle = new Bundle();
            bundle.putInt(CommandReceiver.EXTRA_FLAGS, Context.BIND_INCLUDE_CAPABILITIES);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[2].packageName, 0, bundle);
            // Verify app2 has FOREGROUND_LOCATION capability.
            mWatchers[2].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_FG_SERVICE,
                    new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION | PROCESS_CAPABILITY_NETWORK
                            | PROCESS_CAPABILITY_ALL_IMPLICIT));

            // Back down to foreground service
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
                    mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null);
            // Verify app0 does NOT have FOREGROUND_LOCATION capability.
            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_FG_SERVICE,
                    new Integer(PROCESS_CAPABILITY_ALL_IMPLICIT | PROCESS_CAPABILITY_NETWORK));

            // Remove foreground service as well
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null);
            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_CACHED_EMPTY,
                    new Integer(PROCESS_CAPABILITY_NONE));
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[1].packageName, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    mAppInfo[0].packageName, mAppInfo[2].packageName, 0, null);

            shutdownWatchers();
        }
    }

    /**
     * Test process states for top app binding with and without BIND_INCLUDE_CAPABILITIES flag.
     * Bound app should be TOP w/flag and BTOP without flag.
     * @throws Exception
     */
    @Test
    public void testTopBind() throws Exception {
        setupWatchers(2);

        Activity activity = null;

        try {
            // This will start an activity in App0
            activity = startSubActivity(ScreenOnActivity.class);

            // Bind Stub -> App 0, verify doesn't include capability (only BTOP, not TOP)
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    STUB_PACKAGE_NAME, mAppInfo[0].packageName, 0, null);
            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP,
                    new Integer(PROCESS_CAPABILITY_NETWORK));

            // Bind Stub -> App 1, include capability (TOP)
            Bundle bundle = new Bundle();
            bundle.putInt(CommandReceiver.EXTRA_FLAGS, Context.BIND_INCLUDE_CAPABILITIES);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, bundle);
            mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP,
                    new Integer(PROCESS_CAPABILITY_ALL));
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    STUB_PACKAGE_NAME, mAppInfo[0].packageName, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    STUB_PACKAGE_NAME, mAppInfo[1].packageName, 0, null);

            shutdownWatchers();
            if (activity != null) {
                activity.finish();
            }
        }
    }

    private final <T extends Activity> Activity startSubActivity(Class<T> activityClass) {
        final Instrumentation.ActivityResult result = new Instrumentation.ActivityResult(
                0, new Intent());
        final Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
                activityClass.getName(), result, false);
        mInstrumentation.addMonitor(monitor);
        launchActivity(STUB_PACKAGE_NAME, activityClass, null);
        return monitor.waitForActivity();
    }

    @Test
    public void testCycleTop() throws Exception {
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP2, 0);
        ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP3, 0);

        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP1, android.Manifest.permission.PACKAGE_USAGE_STATS);
        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP2, android.Manifest.permission.PACKAGE_USAGE_STATS);
        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP3, android.Manifest.permission.PACKAGE_USAGE_STATS);

        UidImportanceListener uid1Listener = new UidImportanceListener(mContext,
                app1Info.uid, IMPORTANCE_VISIBLE,
                WAITFOR_MSEC);
        uid1Listener.register();

        UidImportanceListener uid1ServiceListener = new UidImportanceListener(mContext,
                app1Info.uid, IMPORTANCE_CACHED,
                WAITFOR_MSEC);
        uid1ServiceListener.register();

        UidImportanceListener uid2Listener = new UidImportanceListener(mContext,
                app2Info.uid, IMPORTANCE_VISIBLE,
                WAITFOR_MSEC);
        uid2Listener.register();

        UidImportanceListener uid2ServiceListener = new UidImportanceListener(mContext,
                app2Info.uid, IMPORTANCE_CACHED,
                WAITFOR_MSEC);
        uid2ServiceListener.register();

        UidImportanceListener uid3Listener = new UidImportanceListener(mContext,
                app3Info.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE,
                WAITFOR_MSEC);
        uid3Listener.register();

        UidImportanceListener uid3ServiceListener = new UidImportanceListener(mContext,
                app3Info.uid, IMPORTANCE_CACHED,
                WAITFOR_MSEC);
        uid3ServiceListener.register();

        Activity activity = null;

        try {
            // Start an activity
            activity = startSubActivity(ScreenOnActivity.class);

            // Start a FGS in app2
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, PACKAGE_NAME_APP2,
                    PACKAGE_NAME_APP2, 0, null);

            uid2Listener.waitForValue(
                    IMPORTANCE_FOREGROUND_SERVICE,
                    IMPORTANCE_FOREGROUND_SERVICE);

            // Bind from TOP to the service in app1
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null);

            uid1Listener.waitForValue(IMPORTANCE_FOREGROUND,
                    IMPORTANCE_FOREGROUND_SERVICE);

            // Bind from app1 to a service in app2
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);

            // Bind from app2 to a service in app3
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);

            uid3Listener.waitForValue(IMPORTANCE_FOREGROUND,
                    IMPORTANCE_FOREGROUND_SERVICE);

            // Create a cycle
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            try {
                uid3Listener.waitForValue(IMPORTANCE_CACHED,
                        IMPORTANCE_CACHED);
                fail("App3 should not be demoted to cached, expecting FGS");
            } catch (IllegalStateException e) {
                // Didn't go to cached in spite of cycle. Good!
            }

            // Unbind from the TOP app
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null);

            // Check that the apps' proc state is FOREGROUND_SERVICE
            uid2Listener.waitForValue(
                    IMPORTANCE_FOREGROUND_SERVICE,
                    IMPORTANCE_FOREGROUND_SERVICE);

            // Stop the foreground service
            CommandReceiver.sendCommand(mContext, CommandReceiver
                            .COMMAND_STOP_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);

            // Check that the apps fall down to cached state
            uid1ServiceListener.waitForValue(
                    IMPORTANCE_CACHED,
                    IMPORTANCE_CACHED);

            uid2ServiceListener.waitForValue(
                    IMPORTANCE_CACHED,
                    IMPORTANCE_CACHED);

            uid3ServiceListener.waitForValue(
                    IMPORTANCE_CACHED,
                    IMPORTANCE_CACHED);
        } finally {
            // Clean up: unbind services to avoid from interferences with other tests
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP2, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP3, 0, null);
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            uid1Listener.unregister();
            uid1ServiceListener.unregister();
            uid2Listener.unregister();
            uid2ServiceListener.unregister();
            uid3Listener.unregister();
            uid3ServiceListener.unregister();
            if (activity != null) {
                activity.finish();
            }
        }
    }

    @Test
    public void testCycleFgAppAndAlert() throws Exception {
        ApplicationInfo stubInfo = mContext.getPackageManager().getApplicationInfo(
                STUB_PACKAGE_NAME, 0);
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        ApplicationInfo app2Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP2, 0);
        ApplicationInfo app3Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP3, 0);

        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP1, android.Manifest.permission.PACKAGE_USAGE_STATS);
        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP2, android.Manifest.permission.PACKAGE_USAGE_STATS);
        PermissionUtils.grantPermission(
                PACKAGE_NAME_APP3, android.Manifest.permission.PACKAGE_USAGE_STATS);

        UidImportanceListener stubListener = new UidImportanceListener(mContext,
                stubInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE,
                WAITFOR_MSEC);
        stubListener.register();

        UidImportanceListener uid1Listener = new UidImportanceListener(mContext,
                app1Info.uid, IMPORTANCE_VISIBLE,
                WAITFOR_MSEC);
        uid1Listener.register();

        UidImportanceListener uid2Listener = new UidImportanceListener(mContext,
                app2Info.uid, IMPORTANCE_VISIBLE,
                WAITFOR_MSEC);
        uid2Listener.register();

        UidImportanceListener uid3Listener = new UidImportanceListener(mContext,
                app3Info.uid, IMPORTANCE_VISIBLE,
                WAITFOR_MSEC);
        uid3Listener.register();

        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
                WAITFOR_MSEC);
        WatchUidRunner uid3Watcher = new WatchUidRunner(mInstrumentation, app3Info.uid,
                WAITFOR_MSEC);

        try {
            // Stub app should have been in foreground since it's being instrumented.

            PermissionUtils.grantPermission(
                    STUB_PACKAGE_NAME, android.Manifest.permission.SYSTEM_ALERT_WINDOW);
            // Show an alert on app0
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_ALERT_SERVICE, STUB_PACKAGE_NAME,
                    STUB_PACKAGE_NAME, 0, null);

            // Start a FGS in app2
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE, PACKAGE_NAME_APP2,
                    PACKAGE_NAME_APP2, 0, null);

            uid2Listener.waitForValue(IMPORTANCE_FOREGROUND_SERVICE,
                    IMPORTANCE_FOREGROUND_SERVICE);

            // Bind from app0 to a service in app1
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null);

            // Bind from app2 to a service in app1
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, null);

            // Bind from app3 to a service in app1
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            // Create a cycle
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_BIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);

            uid1Listener.waitForValue(IMPORTANCE_FOREGROUND_SERVICE,
                    IMPORTANCE_FOREGROUND_SERVICE);
            uid3Listener.waitForValue(IMPORTANCE_FOREGROUND_SERVICE,
                    IMPORTANCE_FOREGROUND_SERVICE);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    STUB_PACKAGE_NAME, PACKAGE_NAME_APP1, 0, null);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP1, 0, null);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP3, PACKAGE_NAME_APP1, 0, null);

            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP3, 0, null);

            // Stop the foreground service
            CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
                    PACKAGE_NAME_APP2, PACKAGE_NAME_APP2, 0, null);

            // hide the alert
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_STOP_ALERT_SERVICE, STUB_PACKAGE_NAME,
                    STUB_PACKAGE_NAME, 0, null);

            // Check that the apps' proc state has fallen
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid2Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
            uid3Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
        } finally {
            stubListener.unregister();
            uid1Listener.unregister();
            uid2Listener.unregister();
            uid3Listener.unregister();
            uid1Watcher.finish();
            uid2Watcher.finish();
            uid3Watcher.finish();
        }
    }

    /**
     * Test FGS compatibility with START_STICKY flag.
     * @throws Exception
     */
    @Test
    public void testFgsSticky1() throws Exception {
        // For START_STICKY, service is restarted, Service.onStartCommand is called with a null
        // intent.
        testFgsStickyInternal(Service.START_STICKY, ACTION_RESTART_FGS_STICKY_RESULT,
                (uidWatcher, waiter) -> {
                    // After restart, the FGS still has its while-in-use capabilities.
                    uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                            WatchUidRunner.STATE_FG_SERVICE,
                            new Integer(PROCESS_CAPABILITY_ALL));
                    waiter.doWait(WAITFOR_MSEC);
                });
    }

    /**
     * Test FGS compatibility with START_REDELIVER_INTENT flag.
     * @throws Exception
     */
    @Test
    public void testFgsSticky2() throws Exception {
        // For START_REDELIVER_INTENT, service is restarted, Service.onStartCommand is called with
        // the same intent as previous service start.
        testFgsStickyInternal(Service.START_REDELIVER_INTENT, ACTION_START_FGS_RESULT,
                (uidWatcher, waiter) -> {
                    // After restart, the FGS still has its while-in-use capabilities.
                    uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                            WatchUidRunner.STATE_FG_SERVICE,
                            new Integer(PROCESS_CAPABILITY_ALL));
                    waiter.doWait(WAITFOR_MSEC);
                });
    }

    /**
     * Test FGS compatibility with START_NOT_STICKY flag.
     * @throws Exception
     */
    @Test
    public void testFgsSticky3() throws Exception {
        // For START_NOT_STICKY, service does not restart and Service.onStartCommand is not called
        // again.
        testFgsStickyInternal(Service.START_NOT_STICKY, ACTION_RESTART_FGS_STICKY_RESULT,
                (uidWatcher, waiter) -> {
                    try {
                        uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                                WatchUidRunner.STATE_FG_SERVICE);
                        fail("Not-Sticky service should not restart after kill");
                    } catch (Exception e) {
                    }
                    try {
                        waiter.doWait(WAITFOR_MSEC);
                        fail("Not-Sticky service should not call onStartCommand after kill");
                    } catch (Exception e) {
                    }
                });

        testFgsStickyInternal(Service.START_NOT_STICKY, ACTION_START_FGS_RESULT,
                (uidWatcher, waiter) -> {
                    try {
                        uidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                                WatchUidRunner.STATE_FG_SERVICE);
                        fail("Not-Sticky service should not restart after kill");
                    } catch (Exception e) {
                    }
                    try {
                        waiter.doWait(WAITFOR_MSEC);
                        fail("Not-Sticky service should not call onStartCommand after kill");
                    } catch (Exception e) {
                    }
                });
    }

    @Test
    public void testForegroundService_malformedNotificationExtras() throws Exception {
        PermissionUtils.grantPermission(
                STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
        // Use default timeout value 5000
        final ServiceProcessController controller = new ServiceProcessController(mContext,
                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses);

        ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                SIMPLE_PACKAGE_NAME, 0);
        UidImportanceListener uidGoneListener = new UidImportanceListener(mContext,
                appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
        uidGoneListener.register();

        ActivityManager am = mContext.getSystemService(ActivityManager.class);

        try {
            controller.ensureProcessGone();

            // Do initial setup.
            controller.makeUidIdle();
            controller.removeFromWhitelist();
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "allow");

            // Put app on whitelist, to allow service to run.
            controller.addToWhitelist();

            // Add a bad extra to the FGS notification and try to start the service
            // keep key in sync with com.android.cts.launcherapps.simpleapp.SimpleService
            mServiceStartForegroundIntent.putExtra("NotifExtras", true);
            mContext.startService(mServiceStartForegroundIntent);

            // Make sure we crashed the process
            uidGoneListener.waitForValue(IMPORTANCE_GONE, IMPORTANCE_GONE);
            assertEquals(IMPORTANCE_GONE, am.getPackageImportance(SIMPLE_PACKAGE_NAME));
        } finally {
            mContext.stopService(mServiceStartForegroundIntent);
            controller.cleanup();
            controller.setAppOpMode(AppOpsManager.OPSTR_START_FOREGROUND, "ignore");
            controller.removeFromWhitelist();
        }
    }

    private void testFgsStickyInternal(int stickyFlag, String waitForBroadcastAction,
            BiConsumer<WatchUidRunner, WaitForBroadcast> checkKillResult) throws Exception {
        ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                PACKAGE_NAME_APP1, 0);
        WatchUidRunner uid1Watcher = new WatchUidRunner(mInstrumentation, app1Info.uid,
                WAITFOR_MSEC);
        AmMonitor monitor = new AmMonitor(mInstrumentation,
                new String[]{AmMonitor.WAIT_FOR_EARLY_ANR, AmMonitor.WAIT_FOR_ANR});
        try {
            // Start an activity in app1 to put app1 in TOP state, so the FGS it started can have
            // while-in-use capabilities.
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_ACTIVITY,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
                    WatchUidRunner.STATE_TOP,
                    new Integer(PROCESS_CAPABILITY_ALL));

            WaitForBroadcast waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
            waiter.prepare(ACTION_START_FGS_RESULT);
            Bundle extras = new Bundle();
            extras.putInt(LocalForegroundServiceSticky.STICKY_FLAG, stickyFlag);
            CommandReceiver.sendCommand(mContext,
                    CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_STICKY,
                    PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, extras);

            // Launch home activity, so the activity in app1 will be stopped, app1 now only has FGS,
            // we're not "finishing" the activity because removing a task could result in service
            // restart.
            final Intent homeIntent = new Intent();
            homeIntent.setAction(Intent.ACTION_MAIN);
            homeIntent.addCategory(Intent.CATEGORY_HOME);
            homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mTargetContext.startActivity(homeIntent);

            // The FGS has all while-in-use capabilities.
            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
                    new Integer(PROCESS_CAPABILITY_ALL));
            waiter.doWait(WAITFOR_MSEC);

            waiter = new WaitForBroadcast(mInstrumentation.getTargetContext());
            waiter.prepare(waitForBroadcastAction);
            CtsAppTestUtils.executeShellCmd(mInstrumentation,
                    "am crash " + PACKAGE_NAME_APP1);
            monitor.waitFor(AmMonitor.WAIT_FOR_CRASHED, WAITFOR_MSEC);
            monitor.sendCommand(AmMonitor.CMD_KILL);
            checkKillResult.accept(uid1Watcher, waiter);
        } finally {
            final ActivityManager am = mContext.getSystemService(ActivityManager.class);
            SystemUtil.runWithShellPermissionIdentity(() -> {
                am.forceStopPackage(PACKAGE_NAME_APP1);
            });
            uid1Watcher.finish();
            monitor.finish();
        }
    }

    // Copied from android.test.InstrumentationTestCase
    /**
     * Utility method for launching an activity.
     *
     * <p>The {@link Intent} used to launch the Activity is:
     *  action = {@link Intent#ACTION_MAIN}
     *  extras = null, unless a custom bundle is provided here
     * All other fields are null or empty.
     *
     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
     * file.  This is not necessarily the same as the java package name.
     *
     * @param pkg The package hosting the activity to be launched.
     * @param activityCls The activity class to launch.
     * @param extras Optional extra stuff to pass to the activity.
     * @return The activity, or null if non launched.
     */
    public final <T extends Activity> T launchActivity(
            String pkg,
            Class<T> activityCls,
            Bundle extras) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        if (extras != null) {
            intent.putExtras(extras);
        }
        return launchActivityWithIntent(pkg, activityCls, intent);
    }

    // Copied from android.test.InstrumentationTestCase
    /**
     * Utility method for launching an activity with a specific Intent.
     *
     * <p><b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
     * file.  This is not necessarily the same as the java package name.
     *
     * @param pkg The package hosting the activity to be launched.
     * @param activityCls The activity class to launch.
     * @param intent The intent to launch with
     * @return The activity, or null if non launched.
     */
    @SuppressWarnings("unchecked")
    public final <T extends Activity> T launchActivityWithIntent(
            String pkg,
            Class<T> activityCls,
            Intent intent) {
        intent.setClassName(pkg, activityCls.getName());
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        T activity = (T) mInstrumentation.startActivitySync(intent);
        mInstrumentation.waitForIdleSync();
        return activity;
    }
}
