Loading telecomm/java/android/telecom/Phone.java +48 −2 Original line number Diff line number Diff line Loading @@ -32,8 +32,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; /** * A unified virtual device providing a means of voice (and other) communication on a device. Loading Loading @@ -148,6 +150,14 @@ public final class Phone { private final Object mLock = new Object(); // Future used to delay terminating the InCallService before the call disconnect tone // finishes playing. private static Map<String, CompletableFuture<Void>> sDisconnectedToneFutures = new ArrayMap<>(); // Timeout value to be used to ensure future completion for sDisconnectedToneFutures. This is // set to 4 seconds to account for the exceptional case (TONE_CONGESTION). private static final int DISCONNECTED_TONE_TIMEOUT = 4000; Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) { mInCallAdapter = adapter; mCallingPackage = callingPackage; Loading Loading @@ -456,9 +466,45 @@ public final class Phone { } private void fireCallRemoved(Call call) { String callId = call.internalGetCallId(); CompletableFuture<Void> disconnectedToneFuture = initializeDisconnectedToneFuture(callId); // delay the InCallService termination until after the disconnect tone finishes playing disconnectedToneFuture.thenRunAsync(() -> { for (Listener listener : mListeners) { listener.onCallRemoved(this, call); } // clean up the future after sDisconnectedToneFutures.remove(callId); }); } /** * Initialize disconnect tone future to be used in delaying ICS termination. * * @return CompletableFuture to delay InCallService termination until after the disconnect tone * finishes playing. A timeout of 4s is used to handle the use case when we play * TONE_CONGESTION and to ensure completion so that we don't block the removal of the service. */ private CompletableFuture<Void> initializeDisconnectedToneFuture(String callId) { // create the future and map (sDisconnectedToneFutures) it to the corresponding call id CompletableFuture<Void> disconnectedToneFuture = new CompletableFuture<Void>() .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT, TimeUnit.MILLISECONDS); // we should not encounter duplicate insertions since call ids are unique sDisconnectedToneFutures.put(callId, disconnectedToneFuture); return disconnectedToneFuture; } /** * Completes disconnected tone future with passed in result. * @hide * @return true if future was completed, false otherwise */ public static boolean completeDisconnectedToneFuture(String callId) { if (sDisconnectedToneFutures.containsKey(callId)) { sDisconnectedToneFutures.get(callId).complete(null); return true; } return false; } private void fireCallAudioStateChanged(CallAudioState audioState) { Loading Loading
telecomm/java/android/telecom/Phone.java +48 −2 Original line number Diff line number Diff line Loading @@ -32,8 +32,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; /** * A unified virtual device providing a means of voice (and other) communication on a device. Loading Loading @@ -148,6 +150,14 @@ public final class Phone { private final Object mLock = new Object(); // Future used to delay terminating the InCallService before the call disconnect tone // finishes playing. private static Map<String, CompletableFuture<Void>> sDisconnectedToneFutures = new ArrayMap<>(); // Timeout value to be used to ensure future completion for sDisconnectedToneFutures. This is // set to 4 seconds to account for the exceptional case (TONE_CONGESTION). private static final int DISCONNECTED_TONE_TIMEOUT = 4000; Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) { mInCallAdapter = adapter; mCallingPackage = callingPackage; Loading Loading @@ -456,9 +466,45 @@ public final class Phone { } private void fireCallRemoved(Call call) { String callId = call.internalGetCallId(); CompletableFuture<Void> disconnectedToneFuture = initializeDisconnectedToneFuture(callId); // delay the InCallService termination until after the disconnect tone finishes playing disconnectedToneFuture.thenRunAsync(() -> { for (Listener listener : mListeners) { listener.onCallRemoved(this, call); } // clean up the future after sDisconnectedToneFutures.remove(callId); }); } /** * Initialize disconnect tone future to be used in delaying ICS termination. * * @return CompletableFuture to delay InCallService termination until after the disconnect tone * finishes playing. A timeout of 4s is used to handle the use case when we play * TONE_CONGESTION and to ensure completion so that we don't block the removal of the service. */ private CompletableFuture<Void> initializeDisconnectedToneFuture(String callId) { // create the future and map (sDisconnectedToneFutures) it to the corresponding call id CompletableFuture<Void> disconnectedToneFuture = new CompletableFuture<Void>() .completeOnTimeout(null, DISCONNECTED_TONE_TIMEOUT, TimeUnit.MILLISECONDS); // we should not encounter duplicate insertions since call ids are unique sDisconnectedToneFutures.put(callId, disconnectedToneFuture); return disconnectedToneFuture; } /** * Completes disconnected tone future with passed in result. * @hide * @return true if future was completed, false otherwise */ public static boolean completeDisconnectedToneFuture(String callId) { if (sDisconnectedToneFutures.containsKey(callId)) { sDisconnectedToneFutures.get(callId).complete(null); return true; } return false; } private void fireCallAudioStateChanged(CallAudioState audioState) { Loading