1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.car.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.junit.Assume.assumeTrue; 23 24 import android.car.Car; 25 import android.car.remoteaccess.CarRemoteAccessManager; 26 import android.car.remoteaccess.CarRemoteAccessManager.CompletableRemoteTaskFuture; 27 import android.car.remoteaccess.CarRemoteAccessManager.RemoteTaskClientCallback; 28 import android.car.remoteaccess.RemoteTaskClientRegistrationInfo; 29 import android.content.Context; 30 import android.platform.test.annotations.AppModeFull; 31 32 import androidx.annotation.NonNull; 33 import androidx.annotation.Nullable; 34 import androidx.test.platform.app.InstrumentationRegistry; 35 36 import com.android.compatibility.common.util.ApiTest; 37 import com.android.compatibility.common.util.PollingCheck; 38 import com.android.internal.annotations.GuardedBy; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 43 import java.util.concurrent.Executor; 44 45 @AppModeFull(reason = "Instant Apps cannot get car related permissions") 46 public final class CarRemoteAccessManagerTest extends AbstractCarTestCase { 47 48 private static final String TAG = CarRemoteAccessManagerTest.class.getSimpleName(); 49 private static final int CALLBACK_WAIT_TIME_MS = 2_000; 50 private static final String INVALID_TASK_ID = "THIS_ID_CANNOT_BE_VALID_!@#$%^&*()"; 51 52 private Executor mExecutor; 53 private CarRemoteAccessManager mCarRemoteAccessManager; 54 55 @Before setUp()56 public void setUp() throws Exception { 57 assumeTrue("CarRemoteAccessService is not enabled, skipping test", 58 getCar().isFeatureEnabled(Car.CAR_REMOTE_ACCESS_SERVICE)); 59 60 Context context = InstrumentationRegistry.getInstrumentation().getContext(); 61 mExecutor = context.getMainExecutor(); 62 mCarRemoteAccessManager = (CarRemoteAccessManager) getCar() 63 .getCarManager(Car.CAR_REMOTE_ACCESS_SERVICE); 64 assertThat(mCarRemoteAccessManager).isNotNull(); 65 } 66 67 @Test 68 @ApiTest(apis = { 69 "android.car.remoteaccess.CarRemoteAccessManager#" 70 + "setRemoteTaskClient(Executor, RemoteTaskClientCallback)", 71 }) testSetRemoteTaskClient()72 public void testSetRemoteTaskClient() { 73 RemoteTaskClientCallbackImpl callback = new RemoteTaskClientCallbackImpl(); 74 75 mCarRemoteAccessManager.setRemoteTaskClient(mExecutor, callback); 76 77 PollingCheck.waitFor(CALLBACK_WAIT_TIME_MS, () -> callback.getServiceId() != null); 78 PollingCheck.waitFor(CALLBACK_WAIT_TIME_MS, () -> callback.getVehicleId() != null); 79 PollingCheck.waitFor(CALLBACK_WAIT_TIME_MS, () -> callback.getProcessorId() != null); 80 PollingCheck.waitFor(CALLBACK_WAIT_TIME_MS, () -> callback.getClientId() != null); 81 } 82 83 @Test 84 @ApiTest(apis = { 85 "android.car.remoteaccess.CarRemoteAccessManager#" 86 + "setRemoteTaskClient(Executor, RemoteTaskClientCallback)", 87 }) testSetRemoteTaskClient_withAlreadyRegisteredClient()88 public void testSetRemoteTaskClient_withAlreadyRegisteredClient() { 89 RemoteTaskClientCallbackImpl callbackOne = new RemoteTaskClientCallbackImpl(); 90 RemoteTaskClientCallbackImpl callbackTwo = new RemoteTaskClientCallbackImpl(); 91 92 mCarRemoteAccessManager.setRemoteTaskClient(mExecutor, callbackOne); 93 94 assertThrows(IllegalStateException.class, 95 () -> mCarRemoteAccessManager.setRemoteTaskClient(mExecutor, 96 callbackTwo)); 97 } 98 99 @Test 100 @ApiTest(apis = { 101 "android.car.remoteaccess.CarRemoteAccessManager#" 102 + "setRemoteTaskClient(Executor, RemoteTaskClientCallback)", 103 "android.car.remoteaccess.CarRemoteAccessManager#clearRemoteTaskClient" 104 }) testClearRemoteTaskClient()105 public void testClearRemoteTaskClient() { 106 RemoteTaskClientCallbackImpl callback = new RemoteTaskClientCallbackImpl(); 107 mCarRemoteAccessManager.setRemoteTaskClient(mExecutor, callback); 108 109 mCarRemoteAccessManager.clearRemoteTaskClient(); 110 111 // Calling clearRemoteTaskClient again to ensure that multiple calls do not cause errors. 112 mCarRemoteAccessManager.clearRemoteTaskClient(); 113 } 114 115 @Test 116 @ApiTest(apis = {"android.car.remoteaccess.CarRemoteAccessManager#clearRemoteTaskClient"}) testClearRemoteTaskClient_unregisteredClient()117 public void testClearRemoteTaskClient_unregisteredClient() { 118 mCarRemoteAccessManager.clearRemoteTaskClient(); 119 } 120 121 @Test 122 @ApiTest(apis = { 123 "android.car.remoteaccess.CarRemoteAccessManager#reportRemoteTaskDone(String)" 124 }) testReportRemoteTaskDone_unregisteredClient()125 public void testReportRemoteTaskDone_unregisteredClient() { 126 assertThrows(IllegalStateException.class, 127 () -> mCarRemoteAccessManager.reportRemoteTaskDone(INVALID_TASK_ID)); 128 } 129 130 private static final class RemoteTaskClientCallbackImpl implements RemoteTaskClientCallback { 131 private final Object mLock = new Object(); 132 133 @GuardedBy("mLock") 134 private RemoteTaskClientRegistrationInfo mInfo; 135 136 @Override onRegistrationUpdated(@onNull RemoteTaskClientRegistrationInfo info)137 public void onRegistrationUpdated(@NonNull RemoteTaskClientRegistrationInfo info) { 138 synchronized (mLock) { 139 mInfo = info; 140 } 141 } 142 143 @Override onRegistrationFailed()144 public void onRegistrationFailed() { 145 } 146 147 @Override onRemoteTaskRequested(@onNull String taskId, @Nullable byte[] data, int taskMaxDurationInSec)148 public void onRemoteTaskRequested(@NonNull String taskId, @Nullable byte[] data, 149 int taskMaxDurationInSec) { 150 } 151 152 @Override onShutdownStarting(@onNull CompletableRemoteTaskFuture future)153 public void onShutdownStarting(@NonNull CompletableRemoteTaskFuture future) { 154 } 155 getServiceId()156 public String getServiceId() { 157 synchronized (mLock) { 158 return mInfo.getVehicleId(); 159 } 160 } 161 getVehicleId()162 public String getVehicleId() { 163 synchronized (mLock) { 164 return mInfo.getVehicleId(); 165 } 166 } 167 getProcessorId()168 public String getProcessorId() { 169 synchronized (mLock) { 170 return mInfo.getProcessorId(); 171 } 172 } 173 getClientId()174 public String getClientId() { 175 synchronized (mLock) { 176 return mInfo.getClientId(); 177 } 178 } 179 } 180 } 181