1 /* 2 * Copyright (C) 2019 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.server.wm.backgroundactivity.common; 18 19 import android.os.Bundle; 20 import android.os.ConditionVariable; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.ResultReceiver; 24 import android.server.wm.backgroundactivity.common.CommonComponents.Event; 25 26 import java.util.concurrent.TimeoutException; 27 28 /** 29 * Class used to register for events sent via IPC using {@link #getNotifier()} parcelable. 30 * 31 * Create an instance for the event of interest, pass {@link #getNotifier()} to the target, either 32 * via some AIDL or intent extra, have the caller call {@link ResultReceiver#send(int, Bundle)}, 33 * then finally wait for the event with {@link #waitForEventOrThrow(long)}. 34 */ 35 public class EventReceiver { 36 private final Handler mHandler = new Handler(Looper.getMainLooper()); 37 private final ConditionVariable mEventReceivedVariable = new ConditionVariable(false); 38 39 @Event 40 private final int mEvent; 41 EventReceiver(@vent int event)42 public EventReceiver(@Event int event) { 43 mEvent = event; 44 } 45 getNotifier()46 public ResultReceiver getNotifier() { 47 return new ResultReceiver(mHandler) { 48 @Override 49 protected void onReceiveResult(@Event int event, Bundle data) { 50 if (event == mEvent) { 51 mEventReceivedVariable.open(); 52 } 53 } 54 }; 55 } 56 57 /** 58 * Waits for registered event or throws {@link TimeoutException}. 59 */ 60 public void waitForEventOrThrow(long timeoutMs) throws TimeoutException { 61 // Avoid deadlocks 62 if (Thread.currentThread() == mHandler.getLooper().getThread()) { 63 throw new IllegalStateException("This method should be called from different thread"); 64 } 65 66 if (!mEventReceivedVariable.block(timeoutMs)) { 67 throw new TimeoutException("Timed out waiting for event " + mEvent); 68 } 69 } 70 } 71