Merge "Add test for SystemActivityMonitoringService" into nyc-car-dev
diff --git a/tests/carservice_test/AndroidManifest.xml b/tests/carservice_test/AndroidManifest.xml
index 56fa11c..d7c7bdf 100644
--- a/tests/carservice_test/AndroidManifest.xml
+++ b/tests/carservice_test/AndroidManifest.xml
@@ -15,7 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.car.carservicetest"
android:sharedUserId="android.uid.system" >
@@ -36,5 +35,12 @@
<action android:name="android.car.content.pm.CarAppBlockingPolicyService"/>
</intent-filter>
</service>
+ <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityA" />
+ <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityB"
+ android:taskAffinity="com.android.car.carservicetest.activity"/>
+ <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$ActivityC"
+ android:process="com.android.car.carservicetest.activityC"/>
+ <activity android:name="com.android.car.test.SystemActivityMonitoringServiceTest$BlockingActivity"
+ android:taskAffinity="com.android.car.carservicetest.block"/>
</application>
</manifest>
diff --git a/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java b/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
new file mode 100644
index 0000000..3281865
--- /dev/null
+++ b/tests/carservice_test/src/com/android/car/test/SystemActivityMonitoringServiceTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.test;
+
+import android.app.Activity;
+import android.car.test.VehicleHalEmulator;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.SystemClock;
+
+import com.android.car.SystemActivityMonitoringService;
+import com.android.car.SystemActivityMonitoringService.TopTaskInfoContainer;
+import com.android.car.vehiclenetwork.VehicleNetworkConsts;
+import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleDrivingStatus;
+import com.android.car.vehiclenetwork.VehicleNetworkProto;
+import com.android.car.vehiclenetwork.VehiclePropConfigUtil;
+import com.android.car.vehiclenetwork.VehiclePropValueUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class SystemActivityMonitoringServiceTest extends MockedCarTestBase {
+ private static final long TIMEOUT_MS = 3000;
+ private static final long POLL_INTERVAL_MS = 50;
+ private static final Semaphore sAvailable = new Semaphore(0);
+
+ private final DrivingStatusHandler mDrivingStatusHandler = new DrivingStatusHandler();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ getVehicleHalEmulator().addProperty(VehiclePropConfigUtil.getBuilder(
+ VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS,
+ VehicleNetworkConsts.VehiclePropAccess.VEHICLE_PROP_ACCESS_READ,
+ VehicleNetworkConsts.VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE,
+ VehicleNetworkConsts.VehicleValueType.VEHICLE_VALUE_TYPE_INT32,
+ VehicleNetworkConsts.VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY,
+ 0 /*configFlags*/,
+ 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(),
+ mDrivingStatusHandler);
+ }
+
+ private void init(boolean drivingStatusRestricted) {
+ // Set no restriction to driving status, to avoid CarPackageManagerService to launch a
+ // blocking activity.
+ mDrivingStatusHandler.setDrivingStatusRestricted(drivingStatusRestricted);
+ getVehicleHalEmulator().start();
+ VehicleNetworkProto.VehiclePropValue injectValue = VehiclePropValueUtil.createIntValue(
+ VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS, 0,
+ SystemClock.elapsedRealtimeNanos());
+ getVehicleHalEmulator().injectEvent(injectValue);
+ }
+
+ public void testActivityLaunch() {
+ init(false);
+ List<TopTaskInfoContainer> taskList = new ArrayList<>();
+ SystemActivityMonitoringService systemActivityMonitoringService =
+ new SystemActivityMonitoringService(getContext());
+ systemActivityMonitoringService.registerActivityLaunchListener(
+ new SystemActivityMonitoringService.ActivityLaunchListener() {
+ @Override
+ public void onActivityLaunch(
+ SystemActivityMonitoringService.TopTaskInfoContainer topTask) {
+ taskList.add(topTask);
+ }
+ });
+ getContext().startActivity(new Intent(getContext(), ActivityA.class));
+ verifyTopActivityPolling(taskList, 0, new ComponentName(getContext().getPackageName(),
+ ActivityA.class.getName()));
+ sAvailable.release();
+
+ verifyTopActivityPolling(taskList, 1, new ComponentName(getContext().getPackageName(),
+ ActivityB.class.getName()));
+ sAvailable.release();
+
+ verifyTopActivityPolling(taskList, 2, new ComponentName(getContext().getPackageName(),
+ ActivityC.class.getName()));
+ }
+
+ public void testActivityBlocking() {
+ init(false);
+ Semaphore blocked = new Semaphore(0);
+ List<TopTaskInfoContainer> taskList = new ArrayList<>();
+ SystemActivityMonitoringService systemActivityMonitoringService =
+ new SystemActivityMonitoringService(getContext());
+
+ ComponentName blackListedActivity = new ComponentName(getContext().getPackageName(),
+ ActivityC.class.getName());
+ ComponentName blockingActivity = new ComponentName(getContext().getPackageName(),
+ BlockingActivity.class.getName());
+ Intent newActivityIntent = new Intent();
+ newActivityIntent.setComponent(blockingActivity);
+
+ systemActivityMonitoringService.registerActivityLaunchListener(
+ new SystemActivityMonitoringService.ActivityLaunchListener() {
+ @Override
+ public void onActivityLaunch(
+ SystemActivityMonitoringService.TopTaskInfoContainer topTask) {
+ taskList.add(topTask);
+ if (topTask.topActivity.equals(blackListedActivity)) {
+ systemActivityMonitoringService.blockActivity(topTask,
+ newActivityIntent);
+ blocked.release();
+ }
+ }
+ });
+ // start a black listed activity
+ getContext().startActivity(new Intent(getContext(), ActivityC.class));
+ // wait for the listener to call blockActivity()
+ try {
+ blocked.tryAcquire(2, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ fail(e.getMessage());
+ }
+ // We should first receive the blackListedActivity launch,
+ // and later the blockActivity launch
+ verifyTopActivityPolling(taskList, 0, blackListedActivity);
+ verifyTopActivityPolling(taskList, 1, blockingActivity);
+ }
+
+ private void verifyTopActivityPolling(
+ List<TopTaskInfoContainer> topTaskList, int i, ComponentName activity) {
+ boolean activityVerified = false;
+ int timeElapsedMs = 0;
+ try {
+ while (!activityVerified && timeElapsedMs <= TIMEOUT_MS) {
+ Thread.sleep(POLL_INTERVAL_MS);
+ timeElapsedMs += POLL_INTERVAL_MS;
+ if (topTaskList.size() <= i) continue;
+ TopTaskInfoContainer topTask = topTaskList.get(i);
+ if (topTask != null && topTask.topActivity.equals(activity)) {
+ activityVerified = true;
+ break;
+ }
+ }
+ assertEquals(true, activityVerified);
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ }
+
+ public static class ActivityA extends Activity {
+ @Override
+ protected void onPostResume() {
+ super.onPostResume();
+ // Wait until the activity launch event is consumed by the listener.
+ try {
+ if (!sAvailable.tryAcquire(2, TimeUnit.SECONDS)) {
+ fail("Time out");
+ }
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ Intent intent = new Intent(this, ActivityB.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ }
+ }
+
+ public static class ActivityB extends Activity {
+ @Override
+ protected void onPostResume() {
+ super.onPostResume();
+ // Wait until the activity launch event is consumed by the listener.
+ try {
+ if (!sAvailable.tryAcquire(2, TimeUnit.SECONDS)) {
+ fail("Time out");
+ }
+ } catch (Exception e) {
+ fail(e.toString());
+ }
+ Intent intent = new Intent(this, ActivityC.class);
+ startActivity(intent);
+ }
+ }
+
+ public static class ActivityC extends Activity {
+ }
+
+ public static class BlockingActivity extends Activity {
+ }
+
+ private class DrivingStatusHandler implements VehicleHalEmulator.VehicleHalPropertyHandler {
+ int mDrivingStatus =
+ VehicleNetworkConsts.VehicleDrivingStatus.VEHICLE_DRIVING_STATUS_UNRESTRICTED;
+
+ public void setDrivingStatusRestricted(boolean restricted) {
+ mDrivingStatus = restricted ? VehicleDrivingStatus.VEHICLE_DRIVING_STATUS_NO_VIDEO
+ : VehicleDrivingStatus.VEHICLE_DRIVING_STATUS_UNRESTRICTED;
+ }
+
+ @Override
+ public void onPropertySet(VehicleNetworkProto.VehiclePropValue value) {
+ }
+
+ @Override
+ public VehicleNetworkProto.VehiclePropValue onPropertyGet(
+ VehicleNetworkProto.VehiclePropValue value) {
+ return VehiclePropValueUtil.createIntValue(
+ VehicleNetworkConsts.VEHICLE_PROPERTY_DRIVING_STATUS,
+ mDrivingStatus,
+ SystemClock.elapsedRealtimeNanos());
+ }
+
+ @Override
+ public void onPropertySubscribe(int property, float sampleRate, int zones) {
+ }
+
+ @Override
+ public void onPropertyUnsubscribe(int property) {
+ }
+ }
+}
\ No newline at end of file