blob: 328186560fb207dfded6b425c483bf12737dcf41 [file] [log] [blame]
/*
* 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) {
}
}
}