CTS change for process capability.

In ActivityManagerProcessStateTest.java, in foreground service with
location type test cases, when process state changes,
also wait for process capability change, especially watch for
PROCESS_CAPABILITY_FOREGROUND_LOCAION.

Create a test app ActivityManagerApi29 with targetSdkVersion set to 29.
In ActivityManagerApi29Test.java, create test case testFgsLocationWithAppOps()
to test PROCESS_CAPABILITY_FOREGROUND_LOCAION is sent to AppOpsService and
AppOpsService can use it to allow or deny OP_COARSE_LOCATION based on
the uid's process state and capability.

Bug: 136274596
Test: atest android.app.cts.ActivityManagerApi29Test
Change-Id: I437c6772112840b6e9ba917c38cc0972d2139221
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 926b808..29f027e 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -11,6 +11,7 @@
                   -fw apps/CtsVerifier/src/com/android/cts/verifier/usb/
                       apps/CtsVerifierUSBCompanion/
                       libs/
+                      tests/app/
                       tests/autofillservice/
                       tests/contentcaptureservice/
                       tests/tests/animation/
diff --git a/tests/app/ActivityManagerApi29Test/Android.bp b/tests/app/ActivityManagerApi29Test/Android.bp
new file mode 100644
index 0000000..ed3a613
--- /dev/null
+++ b/tests/app/ActivityManagerApi29Test/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2019 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.
+
+android_test_helper_app {
+    name: "CtsActivityManagerApi29",
+    defaults: ["cts_support_defaults"],
+    srcs: ["**/*.java"],
+    // Tag this module as a cts test artifact
+    test_suites: [
+        "cts",
+        "vts",
+        "general-tests",
+    ],
+    sdk_version: "current",
+}
diff --git a/tests/app/ActivityManagerApi29Test/AndroidManifest.xml b/tests/app/ActivityManagerApi29Test/AndroidManifest.xml
new file mode 100644
index 0000000..2ae7497
--- /dev/null
+++ b/tests/app/ActivityManagerApi29Test/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="android.app.cts.activitymanager.api29">
+    <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="29" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+
+    <application android:usesCleartextTraffic="true">
+        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="org.apache.http.legacy" android:required="false" />
+        <activity android:name=".SimpleActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <service android:name="LocationForegroundService"
+            android:foregroundServiceType="location"
+            android:exported="true">
+        </service>
+    </application>
+</manifest>
diff --git a/tests/app/ActivityManagerApi29Test/res/values/colors.xml b/tests/app/ActivityManagerApi29Test/res/values/colors.xml
new file mode 100644
index 0000000..d67d56a
--- /dev/null
+++ b/tests/app/ActivityManagerApi29Test/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2008 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.
+ -->
+
+<resources>
+    <drawable name="black">#77ffffff</drawable>
+</resources>
diff --git a/tests/app/ActivityManagerApi29Test/src/android/app/cts/LocationForegroundService.java b/tests/app/ActivityManagerApi29Test/src/android/app/cts/LocationForegroundService.java
new file mode 100644
index 0000000..86ea295
--- /dev/null
+++ b/tests/app/ActivityManagerApi29Test/src/android/app/cts/LocationForegroundService.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.activitymanager.api29;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class LocationForegroundService extends Service {
+    private static final String NOTIFICATION_CHANNEL_ID =
+            LocationForegroundService.class.getSimpleName();
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        getSystemService(NotificationManager.class).createNotificationChannel(
+                new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
+                NotificationManager.IMPORTANCE_DEFAULT));
+        Notification status = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
+                .setContentTitle("LocalForegroundService running")
+                .setSmallIcon(R.drawable.black)
+                .build();
+        startForeground(1, status);
+        return START_STICKY;
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
+
diff --git a/tests/app/ActivityManagerApi29Test/src/android/app/cts/SimpleActivity.java b/tests/app/ActivityManagerApi29Test/src/android/app/cts/SimpleActivity.java
new file mode 100644
index 0000000..aa28b1f
--- /dev/null
+++ b/tests/app/ActivityManagerApi29Test/src/android/app/cts/SimpleActivity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 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.activitymanager.api29;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * A simple activity to install for various users to test LauncherApps.
+ */
+public class SimpleActivity extends Activity {
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+        if (intent.getExtras().getBoolean("finish")) {
+            finish();
+        }
+    }
+}
diff --git a/tests/app/Android.bp b/tests/app/Android.bp
index 9e25fea..13adccf 100644
--- a/tests/app/Android.bp
+++ b/tests/app/Android.bp
@@ -30,6 +30,7 @@
         "androidx.test.rules",
         "platform-test-annotations",
         "platformprotosnano",
+        "permission-test-util-lib"
     ],
     srcs: ["src/**/*.java"],
     // Tag this module as a cts test artifact
diff --git a/tests/app/AndroidTest.xml b/tests/app/AndroidTest.xml
index 5c2e4cf..36a283e 100644
--- a/tests/app/AndroidTest.xml
+++ b/tests/app/AndroidTest.xml
@@ -33,6 +33,11 @@
         <option name="test-file-name" value="CtsCantSaveState1.apk" />
         <option name="test-file-name" value="CtsCantSaveState2.apk" />
         <option name="test-file-name" value="NotificationDelegator.apk" />
+        <option name="test-file-name" value="CtsActivityManagerApi29.apk" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+        <option name="run-command" value="wm dismiss-keyguard" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/tests/app/src/android/app/cts/ActivityManagerApi29Test.java b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
new file mode 100644
index 0000000..8553698
--- /dev/null
+++ b/tests/app/src/android/app/cts/ActivityManagerApi29Test.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 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.Manifest.permission.ACCESS_COARSE_LOCATION;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
+import static android.app.AppOpsManager.OP_FLAGS_ALL;
+import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
+
+import static com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.HistoricalOp;
+import android.app.AppOpsManager.HistoricalOps;
+import android.app.AppOpsManager.HistoricalOpsRequest;
+import android.app.Instrumentation;
+import android.app.cts.android.app.cts.tools.WatchUidRunner;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.permission.cts.PermissionUtils;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * AppOpsManager.MODE_FOREGROUND is introduced in API level 29. This test class specifically tests
+ * ActivityManagerService's interaction with AppOpsService regarding MODE_FOREGROUND operation.
+ * If an operation's mode is MODE_FOREGROUND, this operation is allowed only when the process is in
+ * one of the foreground state (including foreground_service state), this operation will be denied
+ * when the process is in background state.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ActivityManagerApi29Test {
+    private static final String PACKAGE_NAME = "android.app.cts.activitymanager.api29";
+    private static final String SIMPLE_ACTIVITY = ".SimpleActivity";
+    private static final String SERVICE_NAME = ".LocationForegroundService";
+    private static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
+    private static final int WAITFOR_MSEC = 5000;
+    private static final int NOTEOP_COUNT = 5;
+    private static Instrumentation sInstrumentation = InstrumentationRegistry.getInstrumentation();
+    private static Context sContext = sInstrumentation.getContext();
+    private static AppOpsManager sAppOps =
+            (AppOpsManager) sContext.getSystemService(AppOpsManager.class);
+    private static Intent sServiceIntent = new Intent().setClassName(
+            PACKAGE_NAME, PACKAGE_NAME + SERVICE_NAME);
+    private static int sUid;
+    static {
+        try {
+            sUid = sContext.getPackageManager().getApplicationInfo(PACKAGE_NAME, 0).uid;
+        } catch (NameNotFoundException e) {
+            throw new RuntimeException("NameNotFoundException:" + e);
+        }
+    }
+
+    private String mOldAppOpsSettings;
+    private boolean mWasPermissionsHubEnabled = false;
+    private WatchUidRunner mUidWatcher;
+
+    @Before
+    public void setUp() throws Exception {
+        // PACKAGE_NAME's targetSdkVersion is 29, when ACCESS_COARSE_LOCATION is granted, appOp is
+        // MODE_FOREGROUND (In API level lower than 29, appOp is MODE_ALLOWED).
+        assertEquals(AppOpsManager.MODE_FOREGROUND,
+                PermissionUtils.getAppOp(PACKAGE_NAME, ACCESS_COARSE_LOCATION));
+        runWithShellPermissionIdentity(()-> {
+            mOldAppOpsSettings = Settings.Global.getString(sContext.getContentResolver(),
+                    Settings.Global.APP_OPS_CONSTANTS);
+            Settings.Global.putString(sContext.getContentResolver(),
+                    Settings.Global.APP_OPS_CONSTANTS,
+                    "top_state_settle_time=0,fg_service_state_settle_time=0,"
+                    + "bg_state_settle_time=0");
+            mWasPermissionsHubEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_PERMISSIONS_HUB_ENABLED, false);
+            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_PERMISSIONS_HUB_ENABLED, Boolean.toString(true), false);
+            sAppOps.clearHistory();
+            sAppOps.resetHistoryParameters(); }
+        );
+        mUidWatcher = new WatchUidRunner(sInstrumentation, sUid, WAITFOR_MSEC);
+    }
+
+    @After
+    public void tearDown() {
+        runWithShellPermissionIdentity(() -> {
+            // restore old AppOps settings.
+            Settings.Global.putString(sContext.getContentResolver(),
+                    Settings.Global.APP_OPS_CONSTANTS, mOldAppOpsSettings);
+            DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+                    PROPERTY_PERMISSIONS_HUB_ENABLED, Boolean.toString(mWasPermissionsHubEnabled),
+                    false);
+            sAppOps.clearHistory();
+            sAppOps.resetHistoryParameters(); }
+        );
+        mUidWatcher.finish();
+    }
+
+    /**
+     * This tests app in PROCESS_STATE_TOP state can have location access.
+     * The app's permission is AppOpsManager.MODE_FOREGROUND. If the process is in PROCESS_STATE_TOP
+     * , even its capability is zero, it still has location access.
+     * @throws Exception
+     */
+    @Test
+    public void testTopActivityWithAppOps() throws Exception {
+        Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.setClassName(PACKAGE_NAME, PACKAGE_NAME + SIMPLE_ACTIVITY);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        sContext.startActivity(intent);
+        // TOP process has all capabilities.
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_TOP,
+                new Integer(PROCESS_CAPABILITY_ALL));
+
+        // AppOps location access should be allowed.
+        assertEquals(AppOpsManager.MODE_ALLOWED, noteOp());
+
+        // Tell the activity to finalize.
+        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        intent.putExtra("finish", true);
+        sContext.startActivity(intent);
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_RECENT,
+                new Integer(PROCESS_CAPABILITY_NONE));
+
+        // AppOps location access should be denied.
+        assertEquals(AppOpsManager.MODE_IGNORED, noteOp());
+    }
+
+    /**
+     * When ActivityManagerService process states and capability changes, it updates AppOpsService.
+     * This test starts a foreground service with location type, it updates AppOpsService with
+     * PROCESS_STATE_FOREGROUND_SERVICE and PROCESS_CAPABILITY_FOREGROUND_LOCATION, then check if
+     * AppOpsManager allow ACCESS_COARSE_LOCATION of MODE_FOREGROUND.
+     *
+     * The "android.app.cts.activitymanager.api29" package's targetSdkVersion is 29.
+     * @throws Exception
+     */
+    @Test
+    public void testFgsLocationWithAppOps() throws Exception {
+        // Start a foreground service with location
+        sContext.startForegroundService(sServiceIntent);
+        // Wait for state and capability change.
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
+                new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION));
+
+        // AppOps location access should be allowed.
+        assertEquals(AppOpsManager.MODE_ALLOWED,  noteOp());
+
+        // Stop the foreground service.
+        sContext.stopService(sServiceIntent);
+        // Wait for proc state and capability change.
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
+                new Integer(PROCESS_CAPABILITY_NONE));
+
+        // AppOps location access should be denied.
+        assertEquals(AppOpsManager.MODE_IGNORED, noteOp());
+    }
+
+    /**
+     * After calling AppOpsManager.noteOp() interface multiple times in different process states,
+     * this test calls AppOpsManager.getHistoricalOps() and check the access count and reject count
+     * in HistoricalOps.
+      *
+     * @throws Exception
+     */
+    @Test
+    public void testAppOpsHistoricalOps() throws Exception {
+        // Start a foreground service with location
+        sContext.startForegroundService(sServiceIntent);
+        // Wait for state and capability change.
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE,
+                new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION));
+
+        runWithShellPermissionIdentity(
+                () ->  sAppOps.setHistoryParameters(AppOpsManager.HISTORICAL_MODE_ENABLED_ACTIVE,
+                        1000, 10)
+        );
+        for (int i = 0; i < NOTEOP_COUNT; i++) {
+            noteOp();
+        }
+
+        // Stop the foreground service.
+        sContext.stopService(sServiceIntent);
+        // Wait for proc state and capability change.
+        mUidWatcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY,
+                new Integer(PROCESS_CAPABILITY_NONE));
+
+        for (int i = 0; i < NOTEOP_COUNT; i++) {
+            noteOp();
+        }
+        runWithShellPermissionIdentity(() -> {
+            CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
+            HistoricalOpsRequest histOpsRequest = new HistoricalOpsRequest.Builder(
+                    Instant.now().minus(1, ChronoUnit.HOURS).toEpochMilli(),
+                    Long.MAX_VALUE)
+                    .setUid(sUid)
+                    .setPackageName(PACKAGE_NAME)
+                    .setOpNames(Arrays.asList(AppOpsManager.OPSTR_COARSE_LOCATION))
+                    .setFlags(OP_FLAGS_ALL)
+                    .build();
+            sAppOps.getHistoricalOps(histOpsRequest, sContext.getMainExecutor(), ops::complete);
+            HistoricalOp hOp = ops.get(5000, TimeUnit.MILLISECONDS)
+                    .getUidOps(sUid).getPackageOps(PACKAGE_NAME)
+                    .getOp(AppOpsManager.OPSTR_COARSE_LOCATION);
+            // granted access one time in UID_STATE_FOREGROUND_SERVICE.
+            assertEquals(NOTEOP_COUNT, hOp.getAccessCount(UID_STATE_FOREGROUND_SERVICE,
+                    UID_STATE_FOREGROUND_SERVICE, AppOpsManager.OP_FLAGS_ALL));
+            assertEquals(NOTEOP_COUNT, hOp.getForegroundAccessCount(AppOpsManager.OP_FLAGS_ALL));
+            assertEquals(0, hOp.getForegroundRejectCount(AppOpsManager.OP_FLAGS_ALL));
+            assertEquals(0, hOp.getBackgroundAccessCount(AppOpsManager.OP_FLAGS_ALL));
+            // denied access one time in background.
+            assertEquals(NOTEOP_COUNT, hOp.getBackgroundRejectCount(AppOpsManager.OP_FLAGS_ALL)); }
+        );
+    }
+
+    private int noteOp() throws Exception {
+        return callWithShellPermissionIdentity(
+                () -> sAppOps.noteOp(AppOpsManager.OPSTR_COARSE_LOCATION, sUid, PACKAGE_NAME,
+                        "Op OPSTR_COARSE_LOCATION", ""));
+    }
+}
diff --git a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
index 410ae34..6a23c47 100644
--- a/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerProcessStateTest.java
@@ -16,6 +16,9 @@
 
 package android.app.cts;
 
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+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;
@@ -59,8 +62,6 @@
 import android.util.Log;
 import android.view.accessibility.AccessibilityEvent;
 
-import androidx.test.InstrumentationRegistry;
-
 import com.android.compatibility.common.util.CommonTestUtils;
 import com.android.compatibility.common.util.SystemUtil;
 
@@ -193,7 +194,7 @@
     }
 
     private String executeShellCmd(String cmd) throws Exception {
-        final String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        final String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         Log.d(TAG, String.format("Output for '%s': %s", cmd, result));
         return result;
     }
@@ -235,7 +236,7 @@
     }
 
     private void startActivityAndWaitForShow(final Intent intent) throws Exception {
-        getInstrumentation().getUiAutomation().executeAndWaitForEvent(
+        mInstrumentation.getUiAutomation().executeAndWaitForEvent(
                 () -> {
                     try {
                         mContext.startActivity(intent);
@@ -272,7 +273,7 @@
         UidImportanceListener uidForegroundListener = new UidImportanceListener(mContext,
                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE, WAIT_TIME);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().revokeRuntimePermission(
+        mInstrumentation.getUiAutomation().revokeRuntimePermission(
                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
         boolean gotException = false;
         try {
@@ -282,12 +283,12 @@
         }
         assertTrue("Expected SecurityException thrown", gotException);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
+        mInstrumentation.getUiAutomation().grantRuntimePermission(
                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
         /*
         Log.d("XXXX", "Invoke: " + cmd);
         Log.d("XXXX", "Result: " + result);
-        Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
+        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                 + STUB_PACKAGE_NAME));
         */
         uidForegroundListener.register();
@@ -296,7 +297,7 @@
                 appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
         uidGoneListener.register();
 
-        WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
+        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                 WAIT_TIME);
 
         try {
@@ -440,12 +441,12 @@
 
         ActivityManager am = mContext.getSystemService(ActivityManager.class);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
+        mInstrumentation.getUiAutomation().grantRuntimePermission(
                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
         /*
         Log.d("XXXX", "Invoke: " + cmd);
         Log.d("XXXX", "Result: " + result);
-        Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
+        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                 + STUB_PACKAGE_NAME));
         */
 
@@ -459,7 +460,7 @@
                 appInfo.uid, ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY, WAIT_TIME);
         uidGoneListener.register();
 
-        WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
+        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                 WAIT_TIME);
 
         // First kill the process to start out in a stable state.
@@ -482,7 +483,7 @@
         uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null);
 
         String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // This is a side-effect of the app op command.
         uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
@@ -490,11 +491,11 @@
 
         // 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(getInstrumentation(), cmd);
+        result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // Make sure app is not yet on whitelist
         cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
-        result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // We will use this to monitor when the service is running.
         conn.startMonitoring();
@@ -514,7 +515,7 @@
             // Put app on temporary whitelist to see if this allows the service start.
             cmd = String.format("cmd deviceidle tempwhitelist -d %d %s",
                     TEMP_WHITELIST_DURATION_MS, SIMPLE_PACKAGE_NAME);
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             // Try starting the service now that the app is whitelisted...  should work!
             mContext.startService(serviceIntent);
@@ -540,7 +541,7 @@
 
             // 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(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
             uidWatcher.expect(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
@@ -558,7 +559,7 @@
 
             // Now put app on whitelist, should allow service to run.
             cmd = "cmd deviceidle whitelist +" + SIMPLE_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             // Try starting the service now that the app is whitelisted...  should work!
             mContext.startService(serviceIntent);
@@ -581,9 +582,9 @@
             uidWatcher.finish();
 
             cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             uidGoneListener.unregister();
             uidForegroundListener.unregister();
@@ -605,12 +606,12 @@
 
         ActivityManager am = mContext.getSystemService(ActivityManager.class);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
+        mInstrumentation.getUiAutomation().grantRuntimePermission(
                 STUB_PACKAGE_NAME, android.Manifest.permission.PACKAGE_USAGE_STATS);
         /*
         Log.d("XXXX", "Invoke: " + cmd);
         Log.d("XXXX", "Result: " + result);
-        Log.d("XXXX", SystemUtil.runShellCommand(getInstrumentation(), "dumpsys package "
+        Log.d("XXXX", SystemUtil.runShellCommand(mInstrumentation, "dumpsys package "
                 + STUB_PACKAGE_NAME));
         */
 
@@ -624,7 +625,7 @@
                 appInfo.uid, IMPORTANCE_CACHED, WAIT_TIME);
         uidGoneListener.register();
 
-        WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
+        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                 WAIT_TIME);
 
         // First kill the process to start out in a stable state.
@@ -656,7 +657,7 @@
         uidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, WAIT_TIME);
 
         String cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND deny";
-        String result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // This is a side-effect of the app op command.
         uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
@@ -664,11 +665,11 @@
 
         // 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(getInstrumentation(), cmd);
+        result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // Make sure app is not yet on whitelist
         cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
-        result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         // We will use this to monitor when the service is running.
         conn.startMonitoring();
@@ -726,7 +727,7 @@
 
             // Force app to go idle now
             cmd = "am make-uid-idle " + SIMPLE_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             // Wait for services to be stopped by system.
             uidServiceListener.waitForValue(IMPORTANCE_CACHED,
@@ -752,9 +753,9 @@
             uidWatcher.finish();
 
             cmd = "appops set " + SIMPLE_PACKAGE_NAME + " RUN_IN_BACKGROUND allow";
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             cmd = "cmd deviceidle whitelist -" + SIMPLE_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
             uidGoneListener.unregister();
             uidServiceListener.unregister();
@@ -774,7 +775,7 @@
                 SIMPLE_PACKAGE_NAME + SIMPLE_RECEIVER_START_SERVICE);
 
         final ServiceProcessController controller = new ServiceProcessController(mContext,
-                getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
+                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                 mServiceIntent, WAIT_TIME);
         final WatchUidRunner uidWatcher = controller.getUidWatcher();
@@ -904,7 +905,7 @@
         activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         final ServiceProcessController controller = new ServiceProcessController(mContext,
-                getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
+                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses, WAIT_TIME);
         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                 mServiceIntent, WAIT_TIME);
         final WatchUidRunner uidWatcher = controller.getUidWatcher();
@@ -986,7 +987,7 @@
     public void testForegroundServiceAppOp() throws Exception {
         // Use default timeout value 5000
         final ServiceProcessController controller = new ServiceProcessController(mContext,
-                getInstrumentation(), STUB_PACKAGE_NAME, mAllProcesses);
+                mInstrumentation, STUB_PACKAGE_NAME, mAllProcesses);
         // Use default timeout value 5000
         final ServiceConnectionHandler conn = new ServiceConnectionHandler(mContext,
                 mServiceIntent);
@@ -1248,12 +1249,12 @@
 
         ActivityManager am = mContext.getSystemService(ActivityManager.class);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
+        mInstrumentation.getUiAutomation().grantRuntimePermission(
                 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(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo(
                 CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
@@ -1273,10 +1274,10 @@
                 WAIT_TIME);
         uidCachedListener.register();
 
-        WatchUidRunner uidWatcher = new WatchUidRunner(getInstrumentation(), appInfo.uid,
+        WatchUidRunner uidWatcher = new WatchUidRunner(mInstrumentation, appInfo.uid,
                 WAIT_TIME);
 
-        UiDevice device = UiDevice.getInstance(getInstrumentation());
+        UiDevice device = UiDevice.getInstance(mInstrumentation);
 
         try {
             // Start the heavy-weight app, should launch like a normal app.
@@ -1314,7 +1315,7 @@
             // 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(getInstrumentation(), cmd);
+            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.
@@ -1336,7 +1337,7 @@
             device.waitForIdle();
 
             // Exit activity, check to see if we are now cached.
-            getInstrumentation().getUiAutomation().performGlobalAction(
+            mInstrumentation.getUiAutomation().performGlobalAction(
                     AccessibilityService.GLOBAL_ACTION_BACK);
 
             // Wait for process to become cached
@@ -1352,7 +1353,7 @@
             // 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(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             uidWatcher.expect(WatchUidRunner.CMD_IDLE, null);
 
         } finally {
@@ -1389,25 +1390,25 @@
         homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         ActivityManager am = mContext.getSystemService(ActivityManager.class);
-        UiDevice device = UiDevice.getInstance(getInstrumentation());
+        UiDevice device = UiDevice.getInstance(mInstrumentation);
 
-        InstrumentationRegistry.getInstrumentation().getUiAutomation().grantRuntimePermission(
+        mInstrumentation.getUiAutomation().grantRuntimePermission(
                 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(getInstrumentation(), cmd);
+        String result = SystemUtil.runShellCommand(mInstrumentation, cmd);
         cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
-        result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+        result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         ApplicationInfo app1Info = mContext.getPackageManager().getApplicationInfo(
                 CANT_SAVE_STATE_1_PACKAGE_NAME, 0);
-        WatchUidRunner uid1Watcher = new WatchUidRunner(getInstrumentation(), app1Info.uid,
+        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(getInstrumentation(), app2Info.uid,
+        WatchUidRunner uid2Watcher = new WatchUidRunner(mInstrumentation, app2Info.uid,
                 WAIT_TIME);
 
         try {
@@ -1463,7 +1464,7 @@
 
             // Make sure the original app is idle for cleanliness
             cmd = "am make-uid-idle " + CANT_SAVE_STATE_1_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             uid1Watcher.expect(WatchUidRunner.CMD_IDLE, null);
 
             // Return to home.
@@ -1501,16 +1502,16 @@
             // Exit activity, check to see if we are now cached.
             waitForAppFocus(CANT_SAVE_STATE_1_PACKAGE_NAME, WAIT_TIME);
             device.waitForIdle();
-            getInstrumentation().getUiAutomation().performGlobalAction(
+            mInstrumentation.getUiAutomation().performGlobalAction(
                     AccessibilityService.GLOBAL_ACTION_BACK);
             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(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
             cmd = "am make-uid-idle " + CANT_SAVE_STATE_2_PACKAGE_NAME;
-            result = SystemUtil.runShellCommand(getInstrumentation(), cmd);
+            result = SystemUtil.runShellCommand(mInstrumentation, cmd);
 
         } finally {
             uid2Watcher.finish();
@@ -1743,8 +1744,8 @@
 
     /**
      * Test process states for foreground service with and without location type in the manifest.
-     * When running a foreground service with location type, the process should go to
-     * PROCESS_STATE_FOREGROUND_SERVICE_LOCATION.
+     * When running a foreground service with location type, the process will have
+     * PROCESS_CAPABILITY_FOREGROUND_LOCATION.
      * @throws Exception
      */
     public void testFgsLocation() throws Exception {
@@ -1758,7 +1759,9 @@
             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);
+            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
             // Try to elevate to foreground service location
             Bundle bundle = new Bundle();
@@ -1768,13 +1771,16 @@
                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, bundle);
             uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
-                    WatchUidRunner.STATE_FG_SERVICE_LOCATION);
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION));
 
             // Back down to foreground service
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
             try {
                 uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
@@ -1787,8 +1793,9 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE,
                     PACKAGE_NAME_APP1, PACKAGE_NAME_APP1, 0, null);
-            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_CACHED_EMPTY);
-
+            uid1Watcher.waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_CACHED_EMPTY,
+                    new Integer(PROCESS_CAPABILITY_NONE));
         } finally {
             uid1Watcher.finish();
         }
@@ -1796,8 +1803,11 @@
 
     /**
      * Test process states for foreground service binding to another app, with and without
-     * BIND_INCLUDE_CAPABILITIES. Bound app should either go to FGS or FGSL, depending on the
-     * flag.
+     * 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
      */
     public void testFgsLocationBind() throws Exception {
@@ -1808,7 +1818,9 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE,
                     mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null);
-            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
             // Try to elevate to foreground service location
             Bundle bundle = new Bundle();
@@ -1817,34 +1829,45 @@
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_START_FOREGROUND_SERVICE_LOCATION,
                     mAppInfo[0].packageName, mAppInfo[0].packageName, 0, bundle);
-            // Verify moved to FGSL
+            // Verify app0 has FOREGROUND_LOCATION capability.
             mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
-                    WatchUidRunner.STATE_FG_SERVICE_LOCATION);
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION));
 
-            // Bind App 0 -> App 1, verify doesn't include capabilities (only FGS, not FGSL)
+            // 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);
-            mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+            // Verify app1 does NOT have FOREGROUND_LOCATION capability.
+            mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
-            // Bind App 0 -> App 2, include capabilities (FGSL)
+            // 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_LOCATION);
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_FOREGROUND_LOCATION));
 
             // Back down to foreground service
             CommandReceiver.sendCommand(mContext,
                     CommandReceiver.COMMAND_STOP_FOREGROUND_SERVICE_LOCATION,
                     mAppInfo[0].packageName, mAppInfo[0].packageName, 0, null);
-            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_FG_SERVICE);
+            // Verify app0 does NOT have FOREGROUND_LOCATION capability.
+            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_FG_SERVICE,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
             // 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);
+            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE,
+                    WatchUidRunner.STATE_CACHED_EMPTY,
+                    new Integer(PROCESS_CAPABILITY_NONE));
 
             // Clean up: unbind services to avoid from interferences with other tests
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
@@ -1870,18 +1893,19 @@
             // This will start an activity in App0
             activity = startSubActivity(ScreenOnActivity.class);
 
-            // Bind Stub -> App 0, verify doesn't include capabilities (only BTOP, not TOP)
+            // 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);
+            mWatchers[0].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP,
+                    new Integer(0));
 
-            // Bind Stub -> App 1, include capabilities (TOP)
+            // 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_TOP);
+            mWatchers[1].waitFor(WatchUidRunner.CMD_PROCSTATE, WatchUidRunner.STATE_BOUND_TOP,
+                    new Integer(PROCESS_CAPABILITY_ALL));
 
             // Clean up: unbind services to avoid from interferences with other tests
             CommandReceiver.sendCommand(mContext, CommandReceiver.COMMAND_UNBIND_SERVICE,
diff --git a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
index 01235ae..80c3225 100644
--- a/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
+++ b/tests/app/src/android/app/cts/android/app/cts/tools/ServiceProcessController.java
@@ -215,6 +215,6 @@
             throw new IllegalStateException("Unexpected importance after killing process: "
                     + importance);
         }
-        mUidWatcher.waitFor(WatchUidRunner.CMD_GONE, null, timeout);
+        mUidWatcher.waitFor(WatchUidRunner.CMD_GONE, timeout);
     }
 }
diff --git a/tests/app/src/android/app/cts/android/app/cts/tools/WatchUidRunner.java b/tests/app/src/android/app/cts/android/app/cts/tools/WatchUidRunner.java
index e6e844f..8e631cb 100644
--- a/tests/app/src/android/app/cts/android/app/cts/tools/WatchUidRunner.java
+++ b/tests/app/src/android/app/cts/android/app/cts/tools/WatchUidRunner.java
@@ -47,6 +47,7 @@
     public static final int CMD_UNCACHED = 3;
     public static final int CMD_CACHED = 4;
     public static final int CMD_GONE = 5;
+    public static final int CMD_CAPABILITY = 6;
 
     public static final String STATE_PERSISTENT = "PER";
     public static final String STATE_PERSISTENT_UI = "PERU";
@@ -72,7 +73,7 @@
     public static final String STATE_NONEXISTENT = "NONE";
 
     static final String[] COMMAND_TO_STRING = new String[] {
-            "procstate", "active", "idle", "uncached", "cached", "gone"
+            "procstate", "active", "idle", "uncached", "cached", "gone", "capability"
     };
 
     final Instrumentation mInstrumentation;
@@ -133,7 +134,7 @@
 
     public void expect(int cmd, String procState, long timeout) {
         long waitUntil = SystemClock.uptimeMillis() + timeout;
-        String[] line = waitForNextLine(waitUntil, cmd, procState);
+        String[] line = waitForNextLine(waitUntil, cmd, procState, 0);
         if (!COMMAND_TO_STRING[cmd].equals(line[1])) {
             String msg = "Expected cmd " + COMMAND_TO_STRING[cmd]
                     + " uid " + mUid + " but next report was " + Arrays.toString(line);
@@ -151,26 +152,61 @@
         Log.d(TAG, "Got expected: " + Arrays.toString(line));
     }
 
+    public void waitFor(int cmd) {
+        waitFor(cmd, null, null, mDefaultWaitTime);
+    }
+
+    public void waitFor(int cmd, long timeout) {
+        waitFor(cmd, null, null, timeout);
+    }
+
     public void waitFor(int cmd, String procState) {
-        waitFor(cmd, procState, mDefaultWaitTime);
+        waitFor(cmd, procState, null, mDefaultWaitTime);
+    }
+
+    public void waitFor(int cmd, String procState, Integer capability) {
+        waitFor(cmd, procState, capability, mDefaultWaitTime);
     }
 
     public void waitFor(int cmd, String procState, long timeout) {
+        waitFor(cmd, procState, null, timeout);
+    }
+
+    public void waitFor(int cmd, String procState, Integer capability, long timeout) {
         long waitUntil = SystemClock.uptimeMillis() + timeout;
         while (true) {
-            String[] line = waitForNextLine(waitUntil, cmd, procState);
+            String[] line = waitForNextLine(waitUntil, cmd, procState, capability);
             if (COMMAND_TO_STRING[cmd].equals(line[1])) {
-                if (procState == null) {
+                if (procState == null && capability == null) {
                     Log.d(TAG, "Waited for: " + Arrays.toString(line));
                     return;
                 }
-                if (line.length >= 3 && procState.equals(line[2])) {
-                    Log.d(TAG, "Waited for: " + Arrays.toString(line));
-                    return;
+                if (cmd == CMD_PROCSTATE) {
+                    if (procState != null && capability != null) {
+                        if (procState.equals(line[2]) && capability.toString().equals(line[6])) {
+                            Log.d(TAG, "Waited for: " + Arrays.toString(line));
+                            return;
+                        }
+                    } else if (procState != null) {
+                        if (procState.equals(line[2])) {
+                            Log.d(TAG, "Waited for: " + Arrays.toString(line));
+                            return;
+                        }
+                    } else if (capability != null) {
+                        if (capability.toString().equals(line[6])) {
+                            Log.d(TAG, "Waited for: " + Arrays.toString(line));
+                            return;
+                        }
+                    }
                 } else {
-                    Log.d(TAG, "Skipping because procstate not " + procState + ": "
-                            + Arrays.toString(line));
+                    if (procState != null
+                            && procState.equals(line[2])) {
+                        Log.d(TAG, "Waited for: " + Arrays.toString(line));
+                        return;
+                    }
                 }
+                Log.d(TAG, "Skipping because procstate not " + procState + ": "
+                        + Arrays.toString(line));
             } else {
                 Log.d(TAG, "Skipping because not " + COMMAND_TO_STRING[cmd] + ": "
                         + Arrays.toString(line));
@@ -191,14 +227,15 @@
         }
     }
 
-    String[] waitForNextLine(long waitUntil, int cmd, String procState) {
+    String[] waitForNextLine(long waitUntil, int cmd, String procState, Integer capability) {
         synchronized (mPendingLines) {
             while (true) {
                 while (mPendingLines.size() == 0) {
                     long now = SystemClock.uptimeMillis();
                     if (now >= waitUntil) {
-                        String msg = "Timed out waiting for next line: "
-                                + "cmd=" + COMMAND_TO_STRING[cmd] + " procState=" + procState;
+                        String msg = "Timed out waiting for next line: uid=" + mUidStr
+                                + " cmd=" + COMMAND_TO_STRING[cmd] + " procState=" + procState
+                                + " capability=" + capability;
                         Log.d(TAG, msg);
                         throw new IllegalStateException(msg);
                     }