1 /* 2 * Copyright (C) 2024 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.app.appsearch.testutil.functions; 18 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 23 import java.util.concurrent.CountDownLatch; 24 import java.util.concurrent.TimeUnit; 25 26 /** 27 * Provides utilities to listen to lifecycle events of the {@link TestAppFunctionService}. 28 */ 29 public class TestAppFunctionServiceLifecycleReceiver extends BroadcastReceiver { 30 private static final String ACTION_SERVICE_ON_CREATE = "oncreate"; 31 private static final String ACTION_SERVICE_ON_DESTROY = "ondestroy"; 32 33 private static volatile CountDownLatch sOnCreateLatch = new CountDownLatch(1); 34 private static volatile CountDownLatch sOnDestroyedLatch = new CountDownLatch(1); 35 36 @Override onReceive(Context context, Intent intent)37 public void onReceive(Context context, Intent intent) { 38 if (ACTION_SERVICE_ON_CREATE.equals(intent.getAction())) { 39 sOnCreateLatch.countDown(); 40 } else if (ACTION_SERVICE_ON_DESTROY.equals(intent.getAction())) { 41 sOnDestroyedLatch.countDown(); 42 } 43 } 44 45 /** 46 * Resets the latch and enables another wait cycle. Should never call this method with any 47 * other methods in parallel. 48 */ reset()49 public static void reset() { 50 sOnCreateLatch = new CountDownLatch(1); 51 sOnDestroyedLatch = new CountDownLatch(1); 52 } 53 54 /** 55 * Blocks the current thread until {@link TestAppFunctionService#onDestroy()} is invoked, or the 56 * specified timeout elapses. 57 * 58 * @param timeout The duration to wait for. 59 * @param unit The unit of time for the timeout value. 60 * @return True if the onDestroy was invoked within the timeout, false otherwise. 61 * @throws InterruptedException If the current thread is interrupted while waiting. 62 */ waitForServiceOnDestroy(long timeout, TimeUnit unit)63 public static boolean waitForServiceOnDestroy(long timeout, TimeUnit unit) 64 throws InterruptedException { 65 return sOnDestroyedLatch.await(timeout, unit); 66 } 67 68 /** 69 * Blocks the current thread until {@link TestAppFunctionService#onCreate()} is invoked, or the 70 * specified timeout elapses. 71 * 72 * @param timeout The duration to wait for. 73 * @param unit The unit of time for the timeout value. 74 * @return True if the onCreate was invoked within the timeout, false otherwise. 75 * @throws InterruptedException If the current thread is interrupted while waiting. 76 */ waitForServiceOnCreate(long timeout, TimeUnit unit)77 public static boolean waitForServiceOnCreate(long timeout, TimeUnit unit) 78 throws InterruptedException { 79 return sOnCreateLatch.await(timeout, unit); 80 } 81 82 /** Notifies that {@link TestAppFunctionService} is created. */ notifyOnCreateInvoked(Context context)83 public static void notifyOnCreateInvoked(Context context) { 84 notifyEvent(context, ACTION_SERVICE_ON_CREATE); 85 } 86 87 /** Notifies that {@link TestAppFunctionService} is destroyed. */ notifyOnDestroyInvoked(Context context)88 public static void notifyOnDestroyInvoked(Context context) { 89 notifyEvent(context, ACTION_SERVICE_ON_DESTROY); 90 } 91 notifyEvent(Context context, String action)92 private static void notifyEvent(Context context, String action) { 93 Intent intent = new Intent(context, TestAppFunctionServiceLifecycleReceiver.class); 94 intent.setAction(action); 95 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); 96 context.sendBroadcast(intent); 97 } 98 } 99