diff options
7 files changed, 212 insertions, 13 deletions
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<CallButtonPresenter.CallButto && call.can(android.telecom.Call.Details.CAPABILITY_HOLD); final boolean isCallOnHold = call.getState() == Call.State.ONHOLD; - final boolean showAddCall = TelecomAdapter.getInstance().canAddCall(); + final boolean showAddCall = TelecomAdapter.getInstance().canAddCall(call); final boolean showMerge = call.can( android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE); final boolean showUpgradeToVideo = !isVideo && hasVideoCallCapabilities(call); diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java index 2013a0514..0183b41b9 100644 --- a/InCallUI/src/com/android/incallui/CallCardPresenter.java +++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java @@ -333,7 +333,7 @@ public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi> 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; @@ -13,6 +28,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); + } +} |