From 7a4d2c05103bbf9aa693be1ee7de1286bf7a8256 Mon Sep 17 00:00:00 2001 From: Brandon Maxwell Date: Fri, 11 Dec 2015 16:47:26 -0800 Subject: Backporting InCallServiceImpl In L, InCallService callbacks were implemented through the listener from android.telecom.Phone. To backport, this Listener calls through to the InCallService methods that are overridden in the implementing class Also includes miscellaneous backporting fixes that were missed previously. Change-Id: If8896c72454496459b0e6ea575574161184fba40 --- InCallUI/src/com/android/incallui/Call.java | 2 +- .../com/android/incallui/CallButtonPresenter.java | 2 +- .../com/android/incallui/CallCardPresenter.java | 2 +- .../com/android/incallui/InCallServiceImpl.java | 87 ++++++++++++++++++- .../src/com/android/incallui/TelecomAdapter.java | 14 ++-- .../incallui/compat/telecom/DetailsCompat.java | 21 +++++ .../compat/telecom/InCallServiceCompat.java | 97 ++++++++++++++++++++++ 7 files changed, 212 insertions(+), 13 deletions(-) create mode 100644 InCallUI/src/com/android/incallui/compat/telecom/InCallServiceCompat.java (limited to 'InCallUI') diff --git a/InCallUI/src/com/android/incallui/Call.java b/InCallUI/src/com/android/incallui/Call.java index 0dd7d02b3..9ee27221d 100644 --- a/InCallUI/src/com/android/incallui/Call.java +++ b/InCallUI/src/com/android/incallui/Call.java @@ -429,7 +429,7 @@ public class Call { @Override public void onCallDestroyed(android.telecom.Call call) { Log.d(this, "TelecomCallCallback onStateChanged call=" + call); - call.unregisterCallback(this); + call.removeListener(this); } @Override diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java index ee45f96fc..7e5f7c63f 100644 --- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java +++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java @@ -378,7 +378,7 @@ public class CallButtonPresenter extends Presenter updatePrimaryCallState(); if (call.can(Details.CAPABILITY_MANAGE_CONFERENCE) != - Details.can(details.getCallCapabilities(), Details.CAPABILITY_MANAGE_CONFERENCE)) { + DetailsCompat.can(details, Details.CAPABILITY_MANAGE_CONFERENCE)) { maybeShowManageConferenceCallButton(); } } diff --git a/InCallUI/src/com/android/incallui/InCallServiceImpl.java b/InCallUI/src/com/android/incallui/InCallServiceImpl.java index 3e4f71461..31d6efb92 100644 --- a/InCallUI/src/com/android/incallui/InCallServiceImpl.java +++ b/InCallUI/src/com/android/incallui/InCallServiceImpl.java @@ -18,13 +18,15 @@ package com.android.incallui; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.os.IBinder; +import android.telecom.AudioState; import android.telecom.Call; import android.telecom.CallAudioState; import android.telecom.InCallService; +import android.telecom.Phone; -import com.android.dialer.compat.CallAudioStateCompat; -import com.android.dialer.database.FilteredNumberAsyncQueryHandler; +import com.android.contacts.common.compat.SdkVersionOverride; /** * Used to receive updates about calls from the Telecom component. This service is bound to @@ -34,7 +36,6 @@ import com.android.dialer.database.FilteredNumberAsyncQueryHandler; */ public class InCallServiceImpl extends InCallService { - // TODO CallAudioState backporting blocked by InCallService backporting @Override public void onCallAudioStateChanged(CallAudioState audioState) { AudioModeProvider.getInstance().onAudioStateChanged(audioState.isMuted(), @@ -100,4 +101,84 @@ public class InCallServiceImpl extends InCallService { InCallPresenter.getInstance().tearDown(); } + /* + * Compatibility code for devices running the L sdk. In that version of the sdk, InCallService + * callbacks were registered via a android.telecom.Phone$Listener. These callbacks typically + * correspond 1:1 to callbacks now found in android.telecom.InCallService so the compatibility + * code forwards to those methods. + */ + private Phone.Listener mPhoneListener = new Phone.Listener() { + @Override + public void onAudioStateChanged(Phone phone, AudioState audioState) { + /* + * Need to use reflection here; in M these are private fields retrieved through getters, + * but in L they are public fields without getters. + */ + try { + boolean isMuted = AudioState.class.getField("isMuted").getBoolean(audioState); + int route = AudioState.class.getField("route").getInt(audioState); + int supportedRouteMask = AudioState.class.getField("supportedRouteMask") + .getInt(audioState); + AudioModeProvider.getInstance() + .onAudioStateChanged(isMuted, route, supportedRouteMask); + } catch (ReflectiveOperationException e) { + Log.e(this, "Unable to use reflection to retrieve AudioState fields", e); + } + } + + @Override + public void onBringToForeground(Phone phone, boolean showDialpad) { + InCallServiceImpl.this.onBringToForeground(showDialpad); + } + + @Override + public void onCallAdded(Phone phone, Call call) { + InCallServiceImpl.this.onCallAdded(call); + } + + @Override + public void onCallRemoved(Phone phone, Call call) { + InCallServiceImpl.this.onCallRemoved(call); + } + }; + + private Phone mPhone; + + @Override + public void onPhoneCreated(Phone phone) { + if (SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M) { + return; + } + mPhone = phone; + mPhone.addListener(mPhoneListener); + } + + @Override + public void onPhoneDestroyed(Phone phone) { + if (SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M) { + return; + } + mPhone.removeListener(mPhoneListener); + mPhone = null; + } + + /* + * setMuted and setAudioRoute are final in InCallService so compat methods are + * used to perform the needed branching logic based on sdk version + */ + public void setMutedCompat(boolean state) { + if (SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M) { + super.setMuted(state); + return; + } + mPhone.setMuted(state); + } + + public void setAudioRouteCompat(int route) { + if (SdkVersionOverride.getSdkVersion(Build.VERSION_CODES.M) >= Build.VERSION_CODES.M) { + super.setAudioRoute(route); + return; + } + mPhone.setAudioRoute(route); + } } diff --git a/InCallUI/src/com/android/incallui/TelecomAdapter.java b/InCallUI/src/com/android/incallui/TelecomAdapter.java index 99fcbed55..0fc2e280a 100644 --- a/InCallUI/src/com/android/incallui/TelecomAdapter.java +++ b/InCallUI/src/com/android/incallui/TelecomAdapter.java @@ -16,15 +16,16 @@ package com.android.incallui; +import com.google.common.base.Preconditions; + import android.content.ActivityNotFoundException; import android.content.Intent; import android.os.Looper; import android.telecom.InCallService; import android.telecom.PhoneAccountHandle; -import com.google.common.base.Preconditions; - import com.android.incallui.compat.telecom.DetailsCompat; +import com.android.incallui.compat.telecom.InCallServiceCompat; import java.util.List; @@ -107,7 +108,7 @@ final class TelecomAdapter implements InCallServiceListener { void mute(boolean shouldMute) { if (mInCallService != null) { - mInCallService.setMuted(shouldMute); + InCallServiceCompat.setMuted(mInCallService, shouldMute); } else { Log.e(this, "error mute, mInCallService is null"); } @@ -115,7 +116,7 @@ final class TelecomAdapter implements InCallServiceListener { void setAudioRoute(int route) { if (mInCallService != null) { - mInCallService.setAudioRoute(route); + InCallServiceCompat.setAudioRoute(mInCallService, route); } else { Log.e(this, "error setAudioRoute, mInCallService is null"); } @@ -221,8 +222,7 @@ final class TelecomAdapter implements InCallServiceListener { } } - boolean canAddCall() { - // Default to true if we are not connected to telecom. - return mInCallService == null ? true : mInCallService.canAddCall(); + boolean canAddCall(Call call) { + return InCallServiceCompat.canAddCall(mInCallService, call); } } diff --git a/InCallUI/src/com/android/incallui/compat/telecom/DetailsCompat.java b/InCallUI/src/com/android/incallui/compat/telecom/DetailsCompat.java index fe243408c..c82a972a7 100644 --- a/InCallUI/src/com/android/incallui/compat/telecom/DetailsCompat.java +++ b/InCallUI/src/com/android/incallui/compat/telecom/DetailsCompat.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2015 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.compat.telecom; import android.os.Build; @@ -12,6 +27,12 @@ import com.android.incallui.Log; */ public class DetailsCompat { + /** + * Constant formerly in L as PhoneCapabilities#ADD_CALL. It was transferred to + * {@link Details#CAPABILITY_UNUSED_1} and hidden + */ + public static final int CAPABILITY_UNUSED_1 = 0x00000010; + /** * Returns the intent extras from the given {@link Details} * For Sdk version L and earlier, this will return {@link Details#getExtras()} diff --git a/InCallUI/src/com/android/incallui/compat/telecom/InCallServiceCompat.java b/InCallUI/src/com/android/incallui/compat/telecom/InCallServiceCompat.java new file mode 100644 index 000000000..0a3cb26d4 --- /dev/null +++ b/InCallUI/src/com/android/incallui/compat/telecom/InCallServiceCompat.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2015 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.compat.telecom; + +import android.support.annotation.Nullable; +import android.telecom.InCallService; + +import com.android.contacts.common.compat.CompatUtils; +import com.android.incallui.Call; +import com.android.incallui.InCallServiceImpl; + +/** + * Compatibility class for {@link android.telecom.InCallService} + */ +public class InCallServiceCompat { + + /** + * Sets the microphone mute state. When this request is honored, there + * will be a change to the {@link android.telecom.CallAudioState}. + * + * Note: Noop for Sdk versions less than M where inCallService is not of type + * {@link InCallServiceImpl} + * + * @param inCallService the {@link InCallService} to act on + * @param shouldMute {@code true} if the microphone should be muted; {@code false} otherwise. + */ + public static void setMuted(@Nullable InCallService inCallService, boolean shouldMute) { + if (inCallService == null) { + return; + } + if (CompatUtils.isMarshmallowCompatible()) { + inCallService.setMuted(shouldMute); + return; + } + + if (inCallService instanceof InCallServiceImpl) { + ((InCallServiceImpl) inCallService).setMutedCompat(shouldMute); + } + } + + /** + * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will + * be change to the {@link android.telecom.CallAudioState}. + * + * Note: Noop for Sdk versions less than M where inCallService is not of type + * {@link InCallServiceImpl} + * + * @param inCallService the {@link InCallService} to act on + * @param route The audio route to use. + */ + public static void setAudioRoute(@Nullable InCallService inCallService, int route) { + if (inCallService == null) { + return; + } + if (CompatUtils.isMarshmallowCompatible()) { + inCallService.setAudioRoute(route); + return; + } + + if (inCallService instanceof InCallServiceImpl) { + ((InCallServiceImpl) inCallService).setAudioRouteCompat(route); + } + } + + /** + * Returns if the device can support additional calls. + * + * @param inCallService the {@link InCallService} to act on + * @param call a {@link Call} to use if needed due to compatibility reasons + * @return Whether the phone supports adding more calls, defaulting to true if inCallService + * is null + */ + public static boolean canAddCall(@Nullable InCallService inCallService, Call call) { + if (inCallService == null) { + return true; + } + + if (CompatUtils.isMarshmallowCompatible()) { + // Default to true if we are not connected to telecom. + return inCallService.canAddCall(); + } + return call.can(DetailsCompat.CAPABILITY_UNUSED_1); + } +} -- cgit v1.2.3