From 27c3718f9e3c3297376cfa45f6a67d83a4bb7bcc Mon Sep 17 00:00:00 2001 From: twyen Date: Tue, 24 Apr 2018 11:48:12 -0700 Subject: Expose active calls from in call UI Dual SIM features need to know what phone account the current call is using because usually only one SIM can be in a call at the same time. TEST=TAP Bug: 69675796,72618783 Test: TAP PiperOrigin-RevId: 194121273 Change-Id: I512eb7aca2050f38449b0a911dea9cee9b5ffdb5 --- .../android/dialer/activecalls/ActiveCallInfo.java | 48 ++++++++++++++ .../android/dialer/activecalls/ActiveCalls.java | 34 ++++++++++ .../dialer/activecalls/ActiveCallsComponent.java | 40 ++++++++++++ .../dialer/activecalls/ActiveCallsModule.java | 34 ++++++++++ .../dialer/activecalls/impl/ActiveCallsImpl.java | 45 +++++++++++++ .../binary/aosp/AospDialerRootComponent.java | 2 + .../basecomponent/BaseDialerRootComponent.java | 4 +- .../google/GoogleStubDialerRootComponent.java | 2 + .../dialer/commandline/CommandLineModule.java | 7 ++- .../commandline/impl/ActiveCallsCommand.java | 67 ++++++++++++++++++++ .../incallui/ActiveCallsCallListListener.java | 73 ++++++++++++++++++++++ java/com/android/incallui/InCallPresenter.java | 4 ++ java/com/android/incallui/call/DialerCall.java | 2 +- 13 files changed, 359 insertions(+), 3 deletions(-) create mode 100644 java/com/android/dialer/activecalls/ActiveCallInfo.java create mode 100644 java/com/android/dialer/activecalls/ActiveCalls.java create mode 100644 java/com/android/dialer/activecalls/ActiveCallsComponent.java create mode 100644 java/com/android/dialer/activecalls/ActiveCallsModule.java create mode 100644 java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java create mode 100644 java/com/android/dialer/commandline/impl/ActiveCallsCommand.java create mode 100644 java/com/android/incallui/ActiveCallsCallListListener.java diff --git a/java/com/android/dialer/activecalls/ActiveCallInfo.java b/java/com/android/dialer/activecalls/ActiveCallInfo.java new file mode 100644 index 000000000..d4f76b393 --- /dev/null +++ b/java/com/android/dialer/activecalls/ActiveCallInfo.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.activecalls; + +import android.support.annotation.Nullable; +import android.telecom.PhoneAccountHandle; +import com.google.auto.value.AutoValue; +import com.google.common.base.Optional; + +/** Info of an active call */ +@AutoValue +@SuppressWarnings("Guava") +public abstract class ActiveCallInfo { + + /** The {@link PhoneAccountHandle} the call is made with */ + public abstract Optional phoneAccountHandle(); + + public static Builder builder() { + return new AutoValue_ActiveCallInfo.Builder(); + } + + /** Builder for {@link ActiveCallInfo}. Only In Call UI should create ActiveCallInfo */ + @AutoValue.Builder + public abstract static class Builder { + + public Builder setPhoneAccountHandle(@Nullable PhoneAccountHandle phoneAccountHandle) { + return setPhoneAccountHandle(Optional.fromNullable(phoneAccountHandle)); + } + + public abstract Builder setPhoneAccountHandle(Optional phoneAccountHandle); + + public abstract ActiveCallInfo build(); + } +} diff --git a/java/com/android/dialer/activecalls/ActiveCalls.java b/java/com/android/dialer/activecalls/ActiveCalls.java new file mode 100644 index 000000000..600839c73 --- /dev/null +++ b/java/com/android/dialer/activecalls/ActiveCalls.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.activecalls; + +import android.support.annotation.MainThread; +import com.google.common.collect.ImmutableList; + +/** Exposes information about current active calls to the whole dialer. */ +public interface ActiveCalls { + + /** + * Return a list of current active calls. Any call that is not disconnected is regarded as active. + * Ordering of elements are not guaranteed. + */ + ImmutableList getActiveCalls(); + + /** Should only be called by in call UI. */ + @MainThread + void setActiveCalls(ImmutableList activeCalls); +} diff --git a/java/com/android/dialer/activecalls/ActiveCallsComponent.java b/java/com/android/dialer/activecalls/ActiveCallsComponent.java new file mode 100644 index 000000000..99e0e9493 --- /dev/null +++ b/java/com/android/dialer/activecalls/ActiveCallsComponent.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.activecalls; + +import android.content.Context; +import com.android.dialer.inject.HasRootComponent; +import com.android.dialer.inject.IncludeInDialerRoot; +import dagger.Subcomponent; + +/** Component for {@link ActiveCalls} */ +@Subcomponent +public abstract class ActiveCallsComponent { + + public abstract ActiveCalls activeCalls(); + + public static ActiveCallsComponent get(Context context) { + return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) + .activeCallsComponent(); + } + + /** Used to refer to the root application component. */ + @IncludeInDialerRoot + public interface HasComponent { + ActiveCallsComponent activeCallsComponent(); + } +} diff --git a/java/com/android/dialer/activecalls/ActiveCallsModule.java b/java/com/android/dialer/activecalls/ActiveCallsModule.java new file mode 100644 index 000000000..4d7f44858 --- /dev/null +++ b/java/com/android/dialer/activecalls/ActiveCallsModule.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.activecalls; + +import com.android.dialer.activecalls.impl.ActiveCallsImpl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; +import dagger.Binds; +import dagger.Module; +import javax.inject.Singleton; + +/** Module for {@link ActiveCallsComponent} */ +@Module +@InstallIn(variants = DialerVariant.DIALER_TEST) // TODO(weijiaxu): put all variants. +public abstract class ActiveCallsModule { + + @Singleton + @Binds + public abstract ActiveCalls to(ActiveCallsImpl impl); +} diff --git a/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java b/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java new file mode 100644 index 000000000..3449cc8b0 --- /dev/null +++ b/java/com/android/dialer/activecalls/impl/ActiveCallsImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.activecalls.impl; + +import android.support.annotation.MainThread; +import com.android.dialer.activecalls.ActiveCallInfo; +import com.android.dialer.activecalls.ActiveCalls; +import com.android.dialer.common.Assert; +import com.google.common.collect.ImmutableList; +import javax.inject.Inject; + +/** Implementation of {@link ActiveCalls} */ +public class ActiveCallsImpl implements ActiveCalls { + + ImmutableList activeCalls = ImmutableList.of(); + + @Inject + ActiveCallsImpl() {} + + @Override + public ImmutableList getActiveCalls() { + return activeCalls; + } + + @Override + @MainThread + public void setActiveCalls(ImmutableList activeCalls) { + Assert.isMainThread(); + this.activeCalls = Assert.isNotNull(activeCalls); + } +} diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index 21a282ded..e1021894f 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -17,6 +17,7 @@ package com.android.dialer.binary.aosp; import com.android.bubble.stub.StubBubbleModule; +import com.android.dialer.activecalls.ActiveCallsModule; import com.android.dialer.binary.basecomponent.BaseDialerRootComponent; import com.android.dialer.calllog.CallLogModule; import com.android.dialer.calllog.config.CallLogConfigModule; @@ -49,6 +50,7 @@ import javax.inject.Singleton; @Singleton @Component( modules = { + ActiveCallsModule.class, CallLogModule.class, CallLogConfigModule.class, CommandLineModule.class, diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java index 11e952cbc..75ddaf7f0 100644 --- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java +++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java @@ -17,6 +17,7 @@ package com.android.dialer.binary.basecomponent; import com.android.bubble.BubbleComponent; +import com.android.dialer.activecalls.ActiveCallsComponent; import com.android.dialer.calllog.CallLogComponent; import com.android.dialer.calllog.config.CallLogConfigComponent; import com.android.dialer.calllog.database.CallLogDatabaseComponent; @@ -50,7 +51,8 @@ import com.android.voicemail.VoicemailComponent; * from this component. */ public interface BaseDialerRootComponent - extends BluetoothDeviceProviderComponent.HasComponent, + extends ActiveCallsComponent.HasComponent, + BluetoothDeviceProviderComponent.HasComponent, BubbleComponent.HasComponent, CallLocationComponent.HasComponent, CallLogComponent.HasComponent, diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index 0da2f9577..bdbdeb9dd 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -17,6 +17,7 @@ package com.android.dialer.binary.google; import com.android.bubble.stub.StubBubbleModule; +import com.android.dialer.activecalls.ActiveCallsModule; import com.android.dialer.binary.basecomponent.BaseDialerRootComponent; import com.android.dialer.calllog.CallLogModule; import com.android.dialer.calllog.config.CallLogConfigModule; @@ -52,6 +53,7 @@ import javax.inject.Singleton; @Singleton @Component( modules = { + ActiveCallsModule.class, CallLocationModule.class, CallLogModule.class, CallLogConfigModule.class, diff --git a/java/com/android/dialer/commandline/CommandLineModule.java b/java/com/android/dialer/commandline/CommandLineModule.java index 915578722..c78de21e5 100644 --- a/java/com/android/dialer/commandline/CommandLineModule.java +++ b/java/com/android/dialer/commandline/CommandLineModule.java @@ -16,6 +16,7 @@ package com.android.dialer.commandline; +import com.android.dialer.commandline.impl.ActiveCallsCommand; import com.android.dialer.commandline.impl.BlockingCommand; import com.android.dialer.commandline.impl.CallCommand; import com.android.dialer.commandline.impl.Echo; @@ -45,6 +46,7 @@ public abstract class CommandLineModule { private final Echo echo; private final BlockingCommand blockingCommand; private final CallCommand callCommand; + private final ActiveCallsCommand activeCallsCommand; @Inject AospCommandInjector( @@ -52,12 +54,14 @@ public abstract class CommandLineModule { Version version, Echo echo, BlockingCommand blockingCommand, - CallCommand callCommand) { + CallCommand callCommand, + ActiveCallsCommand activeCallsCommand) { this.help = help; this.version = version; this.echo = echo; this.blockingCommand = blockingCommand; this.callCommand = callCommand; + this.activeCallsCommand = activeCallsCommand; } public CommandSupplier.Builder inject(CommandSupplier.Builder builder) { @@ -66,6 +70,7 @@ public abstract class CommandLineModule { builder.addCommand("echo", echo); builder.addCommand("blocking", blockingCommand); builder.addCommand("call", callCommand); + builder.addCommand("activecalls", activeCallsCommand); return builder; } } diff --git a/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java b/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java new file mode 100644 index 000000000..81641ed50 --- /dev/null +++ b/java/com/android/dialer/commandline/impl/ActiveCallsCommand.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.commandline.impl; + +import android.content.Context; +import android.support.annotation.NonNull; +import com.android.dialer.activecalls.ActiveCallsComponent; +import com.android.dialer.commandline.Arguments; +import com.android.dialer.commandline.Command; +import com.android.dialer.inject.ApplicationContext; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import javax.inject.Inject; + +/** Manipulates {@link com.android.dialer.activecalls.ActiveCalls} */ +public class ActiveCallsCommand implements Command { + + private final Context appContext; + + @Inject + ActiveCallsCommand(@ApplicationContext Context appContext) { + this.appContext = appContext; + } + + @NonNull + @Override + public String getShortDescription() { + return "manipulate active calls"; + } + + @NonNull + @Override + public String getUsage() { + return "activecalls list"; + } + + @Override + public ListenableFuture run(Arguments args) throws IllegalCommandLineArgumentException { + if (args.getPositionals().isEmpty()) { + return Futures.immediateFuture(getUsage()); + } + + String command = args.getPositionals().get(0); + + switch (command) { + case "list": + return Futures.immediateFuture( + ActiveCallsComponent.get(appContext).activeCalls().getActiveCalls().toString()); + default: + throw new IllegalCommandLineArgumentException("unknown command " + command); + } + } +} diff --git a/java/com/android/incallui/ActiveCallsCallListListener.java b/java/com/android/incallui/ActiveCallsCallListListener.java new file mode 100644 index 000000000..ce9f9a36d --- /dev/null +++ b/java/com/android/incallui/ActiveCallsCallListListener.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.incallui; + +import android.content.Context; +import android.support.annotation.NonNull; +import com.android.dialer.activecalls.ActiveCallInfo; +import com.android.dialer.activecalls.ActiveCallsComponent; +import com.android.incallui.call.CallList; +import com.android.incallui.call.DialerCall; +import com.android.incallui.call.DialerCall.State; +import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; + +/** Updates {@link com.android.dialer.activecalls.ActiveCalls} */ +@SuppressWarnings("Guava") +public class ActiveCallsCallListListener implements CallList.Listener { + + private final Context appContext; + + ActiveCallsCallListListener(Context appContext) { + this.appContext = appContext; + } + + @Override + public void onIncomingCall(DialerCall call) {} + + @Override + public void onUpgradeToVideo(DialerCall call) {} + + @Override + public void onSessionModificationStateChange(DialerCall call) {} + + @Override + public void onCallListChange(CallList callList) { + ImmutableList.Builder activeCalls = ImmutableList.builder(); + for (DialerCall call : callList.getAllCalls()) { + if (call.getState() != State.DISCONNECTED) { + activeCalls.add( + ActiveCallInfo.builder() + .setPhoneAccountHandle(Optional.fromNullable(call.getAccountHandle())) + .build()); + } + } + ActiveCallsComponent.get(appContext).activeCalls().setActiveCalls(activeCalls.build()); + } + + @Override + public void onDisconnect(DialerCall call) {} + + @Override + public void onWiFiToLteHandover(DialerCall call) {} + + @Override + public void onHandoverToWifiFailed(DialerCall call) {} + + @Override + public void onInternationalCallOnWifi(@NonNull DialerCall call) {} +} diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java index 5e08c6969..a67dab513 100644 --- a/java/com/android/incallui/InCallPresenter.java +++ b/java/com/android/incallui/InCallPresenter.java @@ -197,6 +197,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud private InCallCameraManager inCallCameraManager; private FilteredNumberAsyncQueryHandler filteredQueryHandler; private CallList.Listener spamCallListListener; + private CallList.Listener activeCallsListener; /** Whether or not we are currently bound and waiting for Telecom to send us a new call. */ private boolean boundAndWaitingForOutgoingCall; /** Determines if the InCall UI is in fullscreen mode or not. */ @@ -383,6 +384,8 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud new SpamCallListListener( context, DialerExecutorComponent.get(context).dialerExecutorFactory()); this.callList.addListener(spamCallListListener); + activeCallsListener = new ActiveCallsCallListListener(context); + this.callList.addListener(activeCallsListener); VideoPauseController.getInstance().setUp(this); @@ -858,6 +861,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud callList.getActiveOrBackgroundCall() != null || callList.getOutgoingCall() != null; inCallActivity.dismissKeyguard(hasCall); } + Trace.endSection(); } diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java index c153503ac..9dfe7abcb 100644 --- a/java/com/android/incallui/call/DialerCall.java +++ b/java/com/android/incallui/call/DialerCall.java @@ -157,7 +157,7 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa private String lastForwardedNumber; private boolean isCallForwarded; private String callSubject; - private PhoneAccountHandle phoneAccountHandle; + @Nullable private PhoneAccountHandle phoneAccountHandle; @CallHistoryStatus private int callHistoryStatus = CALL_HISTORY_STATUS_UNKNOWN; private boolean isSpam; private boolean isBlocked; -- cgit v1.2.3