1 /* 2 * Copyright (C) 2022 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 package android.wearable.cts; 17 18 import android.app.ambientcontext.AmbientContextEventRequest; 19 import android.app.ambientcontext.AmbientContextManager; 20 import android.os.ParcelFileDescriptor; 21 import android.os.PersistableBundle; 22 import android.os.SharedMemory; 23 import android.service.ambientcontext.AmbientContextDetectionResult; 24 import android.service.ambientcontext.AmbientContextDetectionServiceStatus; 25 import android.service.wearable.WearableSensingService; 26 import android.util.Log; 27 28 import java.util.Set; 29 import java.util.concurrent.CountDownLatch; 30 import java.util.concurrent.TimeUnit; 31 import java.util.function.Consumer; 32 33 /** An implementation of {@link WearableSensingService} for CTS testing. */ 34 public class CtsWearableSensingService extends WearableSensingService { 35 private static final String TAG = "CtsWearableSensingService"; 36 private static final String FAKE_APP_PACKAGE = "foo.bar.baz"; 37 private static final int INITIAL_STATUS_TO_CONSUME = -1; 38 39 private static final AmbientContextDetectionServiceStatus INITIAL_SERVICE_STATUS_TO_CONSUME = 40 new AmbientContextDetectionServiceStatus.Builder(FAKE_APP_PACKAGE).setStatusCode( 41 AmbientContextManager.STATUS_UNKNOWN).build(); 42 43 private static CountDownLatch sRespondLatch = new CountDownLatch(1); 44 private static Consumer<Integer> sStatusConsumer; 45 private static int sStatusToConsume; 46 private static ParcelFileDescriptor sParcelFileDescriptor; 47 private static SharedMemory sSharedMemory; 48 private static PersistableBundle sData; 49 50 private static Consumer<AmbientContextDetectionResult> sDetectionResultConsumer; 51 private static Consumer<AmbientContextDetectionServiceStatus> 52 sAmbientContextDetectionServiceStatusConsumer; 53 private static AmbientContextDetectionServiceStatus sServiceStatusToConsume; 54 private static String sPackageName = null; 55 56 @Override onDataStreamProvided(ParcelFileDescriptor parcelFileDescriptor, Consumer<Integer> statusConsumer)57 public void onDataStreamProvided(ParcelFileDescriptor parcelFileDescriptor, 58 Consumer<Integer> statusConsumer) { 59 Log.w(TAG, "onDataStreamProvided"); 60 sParcelFileDescriptor = parcelFileDescriptor; 61 sStatusConsumer = statusConsumer; 62 sRespondLatch.countDown(); 63 } 64 65 @Override onDataProvided(PersistableBundle data, SharedMemory sharedMemory, Consumer<Integer> statusConsumer)66 public void onDataProvided(PersistableBundle data, SharedMemory sharedMemory, 67 Consumer<Integer> statusConsumer) { 68 Log.w(TAG, "onDataProvided"); 69 sData = data; 70 sSharedMemory = sharedMemory; 71 sStatusConsumer = statusConsumer; 72 sRespondLatch.countDown(); 73 } 74 75 @Override onStartDetection(AmbientContextEventRequest request, String packageName, Consumer<AmbientContextDetectionServiceStatus> statusConsumer, Consumer<AmbientContextDetectionResult> detectionResultConsumer)76 public void onStartDetection(AmbientContextEventRequest request, 77 String packageName, 78 Consumer<AmbientContextDetectionServiceStatus> statusConsumer, 79 Consumer<AmbientContextDetectionResult> detectionResultConsumer) { 80 Log.w(TAG, "onStartDetection"); 81 sPackageName = packageName; 82 sDetectionResultConsumer = detectionResultConsumer; 83 sAmbientContextDetectionServiceStatusConsumer = statusConsumer; 84 sRespondLatch.countDown(); 85 } 86 87 @Override onStopDetection(String packageName)88 public void onStopDetection(String packageName) { 89 Log.w(TAG, "onStopDetection"); 90 sPackageName = packageName; 91 sRespondLatch.countDown(); 92 } 93 94 @Override onQueryServiceStatus(Set<Integer> eventTypes, String packageName, Consumer<AmbientContextDetectionServiceStatus> consumer)95 public void onQueryServiceStatus(Set<Integer> eventTypes, 96 String packageName, 97 Consumer<AmbientContextDetectionServiceStatus> consumer) { 98 Log.w(TAG, "onQueryServiceStatus"); 99 sPackageName = packageName; 100 sAmbientContextDetectionServiceStatusConsumer = consumer; 101 sRespondLatch.countDown(); 102 } 103 reset()104 public static void reset() { 105 sRespondLatch = new CountDownLatch(1); 106 sStatusConsumer = null; 107 sStatusToConsume = INITIAL_STATUS_TO_CONSUME; 108 sParcelFileDescriptor = null; 109 sSharedMemory = null; 110 sData = null; 111 sDetectionResultConsumer = null; 112 sAmbientContextDetectionServiceStatusConsumer = null; 113 sServiceStatusToConsume = null; 114 sPackageName = null; 115 } 116 whenCallbackTriggeredRespondWithStatus(int status)117 public static void whenCallbackTriggeredRespondWithStatus(int status) { 118 Log.w(TAG, "whenCallbackTriggeredRespondWithStatus"); 119 sStatusToConsume = status; 120 } 121 whenCallbackTriggeredRespondWithServiceStatus(int status)122 public static void whenCallbackTriggeredRespondWithServiceStatus(int status) { 123 sServiceStatusToConsume = new AmbientContextDetectionServiceStatus.Builder( 124 FAKE_APP_PACKAGE).setStatusCode(status).build(); 125 } 126 expectTimeOut()127 public static void expectTimeOut() { 128 try { 129 if (!sRespondLatch.await(3000, TimeUnit.MILLISECONDS)) { 130 Log.e(TAG, "Timed out waiting for result, this is expected"); 131 } else { 132 throw new AssertionError("CtsWearableSensingService" 133 + " expected timeout but did not timeout."); 134 } 135 // reset for next 136 sRespondLatch = new CountDownLatch(1); 137 sStatusToConsume = AmbientContextManager.STATUS_UNKNOWN; 138 } catch (InterruptedException e) { 139 Log.e(TAG, e.getMessage()); 140 Thread.currentThread().interrupt(); 141 throw new AssertionError("Got InterruptedException while waiting for serviceStatus."); 142 } 143 } 144 awaitResultAmbientContextDetectionService()145 public static void awaitResultAmbientContextDetectionService() { 146 try { 147 if (!sRespondLatch.await(3000, TimeUnit.MILLISECONDS)) { 148 throw new AssertionError("CtsWearableSensingService" 149 + " timed out while expecting a call."); 150 } 151 sAmbientContextDetectionServiceStatusConsumer.accept(sServiceStatusToConsume); 152 // reset for next 153 sRespondLatch = new CountDownLatch(1); 154 sServiceStatusToConsume = INITIAL_SERVICE_STATUS_TO_CONSUME; 155 } catch (InterruptedException e) { 156 Log.e(TAG, e.getMessage()); 157 Thread.currentThread().interrupt(); 158 throw new AssertionError("Got InterruptedException while waiting for serviceStatus."); 159 } 160 } 161 awaitResult()162 public static void awaitResult() { 163 try { 164 if (!sRespondLatch.await(3000, TimeUnit.MILLISECONDS)) { 165 throw new AssertionError("CtsWearableSensingService" 166 + " timed out while expecting a call."); 167 } 168 sStatusConsumer.accept(sStatusToConsume); 169 // reset for next 170 sRespondLatch = new CountDownLatch(1); 171 sStatusToConsume = INITIAL_STATUS_TO_CONSUME; 172 } catch (InterruptedException e) { 173 Log.e(TAG, e.getMessage()); 174 Thread.currentThread().interrupt(); 175 throw new AssertionError("Got InterruptedException while waiting for serviceStatus."); 176 } 177 } 178 179 getData()180 public static PersistableBundle getData() { 181 return sData; 182 } 183 getParcelFileDescriptor()184 public static ParcelFileDescriptor getParcelFileDescriptor() { 185 return sParcelFileDescriptor; 186 } 187 getLastCallingPackage()188 public static String getLastCallingPackage() { 189 return sPackageName; 190 } 191 } 192