From ee4a3feabd047f27540c5967b88d407855f3de8a Mon Sep 17 00:00:00 2001 From: Santos Cordon Date: Tue, 6 Aug 2013 19:06:19 -0700 Subject: Audio Routing support in UI Changes: - AudioModeProvider - receives audio mode changes from CallHandlerService - CallButtonPresenter listens to AudioModeProvider so that it can use those changes in the UI. - CallButtonFragment uses the audio mode from Presenter() to display: - The correct layers for the supported modes - The popup menu when bluetooth is enabled Change-Id: I8ec4024f7bbb5e3b1cfdaae20a4dd2f85ae802cf --- .../res/drawable-hdpi/ic_ab_dialer_holo_dark.png | Bin 0 -> 1487 bytes .../res/drawable-hdpi/ic_bluetooth_holo_dark.png | Bin 0 -> 1852 bytes .../drawable-ldrtl-hdpi/ic_ab_dialer_holo_dark.png | Bin 0 -> 5665 bytes .../drawable-ldrtl-mdpi/ic_ab_dialer_holo_dark.png | Bin 0 -> 5014 bytes .../ic_ab_dialer_holo_dark.png | Bin 0 -> 6513 bytes .../res/drawable-mdpi/ic_ab_dialer_holo_dark.png | Bin 0 -> 1019 bytes .../res/drawable-mdpi/ic_bluetooth_holo_dark.png | Bin 0 -> 1228 bytes .../res/drawable-xhdpi/ic_ab_dialer_holo_dark.png | Bin 0 -> 2116 bytes .../res/drawable-xhdpi/ic_bluetooth_holo_dark.png | Bin 0 -> 2558 bytes InCallUI/res/menu/incall_audio_mode_menu.xml | 38 +++ .../src/com/android/incallui/AnswerFragment.java | 5 + .../com/android/incallui/AudioModeProvider.java | 89 +++++++ .../com/android/incallui/CallButtonFragment.java | 288 +++++++++++++++++++-- .../com/android/incallui/CallButtonPresenter.java | 95 +++++-- .../src/com/android/incallui/CallCardFragment.java | 6 + .../com/android/incallui/CallCommandClient.java | 4 +- .../com/android/incallui/CallHandlerService.java | 27 +- InCallUI/src/com/android/incallui/Presenter.java | 7 + 18 files changed, 513 insertions(+), 46 deletions(-) create mode 100644 InCallUI/res/drawable-hdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-hdpi/ic_bluetooth_holo_dark.png create mode 100644 InCallUI/res/drawable-ldrtl-hdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-ldrtl-mdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-ldrtl-xhdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-mdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-mdpi/ic_bluetooth_holo_dark.png create mode 100644 InCallUI/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png create mode 100644 InCallUI/res/drawable-xhdpi/ic_bluetooth_holo_dark.png create mode 100644 InCallUI/res/menu/incall_audio_mode_menu.xml create mode 100644 InCallUI/src/com/android/incallui/AudioModeProvider.java diff --git a/InCallUI/res/drawable-hdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-hdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..ecfeb2db8 Binary files /dev/null and b/InCallUI/res/drawable-hdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-hdpi/ic_bluetooth_holo_dark.png b/InCallUI/res/drawable-hdpi/ic_bluetooth_holo_dark.png new file mode 100644 index 000000000..ba22b0f8d Binary files /dev/null and b/InCallUI/res/drawable-hdpi/ic_bluetooth_holo_dark.png differ diff --git a/InCallUI/res/drawable-ldrtl-hdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-ldrtl-hdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..7ec3709bb Binary files /dev/null and b/InCallUI/res/drawable-ldrtl-hdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-ldrtl-mdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-ldrtl-mdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..6020b3de1 Binary files /dev/null and b/InCallUI/res/drawable-ldrtl-mdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-ldrtl-xhdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-ldrtl-xhdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..c42e7e391 Binary files /dev/null and b/InCallUI/res/drawable-ldrtl-xhdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-mdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-mdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..51ad9e375 Binary files /dev/null and b/InCallUI/res/drawable-mdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-mdpi/ic_bluetooth_holo_dark.png b/InCallUI/res/drawable-mdpi/ic_bluetooth_holo_dark.png new file mode 100644 index 000000000..fb69031dc Binary files /dev/null and b/InCallUI/res/drawable-mdpi/ic_bluetooth_holo_dark.png differ diff --git a/InCallUI/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png b/InCallUI/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png new file mode 100644 index 000000000..3f43a8221 Binary files /dev/null and b/InCallUI/res/drawable-xhdpi/ic_ab_dialer_holo_dark.png differ diff --git a/InCallUI/res/drawable-xhdpi/ic_bluetooth_holo_dark.png b/InCallUI/res/drawable-xhdpi/ic_bluetooth_holo_dark.png new file mode 100644 index 000000000..24cb8939d Binary files /dev/null and b/InCallUI/res/drawable-xhdpi/ic_bluetooth_holo_dark.png differ diff --git a/InCallUI/res/menu/incall_audio_mode_menu.xml b/InCallUI/res/menu/incall_audio_mode_menu.xml new file mode 100644 index 000000000..013989500 --- /dev/null +++ b/InCallUI/res/menu/incall_audio_mode_menu.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + diff --git a/InCallUI/src/com/android/incallui/AnswerFragment.java b/InCallUI/src/com/android/incallui/AnswerFragment.java index 196a66bb0..79247c56c 100644 --- a/InCallUI/src/com/android/incallui/AnswerFragment.java +++ b/InCallUI/src/com/android/incallui/AnswerFragment.java @@ -68,6 +68,11 @@ public class AnswerFragment extends BaseFragment implements return glowPad; } + @Override + public void onDestroyView() { + getPresenter().onUiUnready(this); + } + @Override public void showAnswerUi(boolean show) { getView().setVisibility(show ? View.VISIBLE : View.GONE); diff --git a/InCallUI/src/com/android/incallui/AudioModeProvider.java b/InCallUI/src/com/android/incallui/AudioModeProvider.java new file mode 100644 index 000000000..abbbfb6e6 --- /dev/null +++ b/InCallUI/src/com/android/incallui/AudioModeProvider.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 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 com.google.android.collect.Lists; + +import com.android.services.telephony.common.AudioMode; + +import java.util.List; + + +/** + * Proxy class for getting and setting the audio mode. + */ +/* package */ class AudioModeProvider { + + private static AudioModeProvider sAudioModeProvider; + private int mAudioMode = AudioMode.EARPIECE; + private int mSupportedModes = AudioMode.ALL_MODES; + private final List mListeners = Lists.newArrayList(); + + public static synchronized AudioModeProvider getInstance() { + if (sAudioModeProvider == null) { + sAudioModeProvider = new AudioModeProvider(); + } + return sAudioModeProvider; + } + + /** + * Access only through getInstance() + */ + private AudioModeProvider() { + } + + public void onAudioModeChange(int newMode) { + mAudioMode = newMode; + + for (AudioModeListener l : mListeners) { + l.onAudioMode(mAudioMode); + } + } + + public void onSupportedAudioModeChange(int newModeMask) { + mSupportedModes = newModeMask; + + for (AudioModeListener l : mListeners) { + l.onSupportedAudioMode(mSupportedModes); + } + } + + public void addListener(AudioModeListener listener) { + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } + } + + public void removeListener(AudioModeListener listener) { + if (mListeners.contains(listener)) { + mListeners.remove(listener); + } + } + + public int getSupportedModes() { + return mSupportedModes; + } + + public int getAudioMode() { + return mAudioMode; + } + + /* package */ interface AudioModeListener { + void onAudioMode(int newMode); + void onSupportedAudioMode(int modeMask); + } +} diff --git a/InCallUI/src/com/android/incallui/CallButtonFragment.java b/InCallUI/src/com/android/incallui/CallButtonFragment.java index 772251dfa..175fe4d95 100644 --- a/InCallUI/src/com/android/incallui/CallButtonFragment.java +++ b/InCallUI/src/com/android/incallui/CallButtonFragment.java @@ -17,39 +17,48 @@ package com.android.incallui; import android.content.Context; +import android.graphics.drawable.LayerDrawable; import android.media.AudioManager; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; +import android.widget.PopupMenu; +import android.widget.PopupMenu.OnDismissListener; +import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.ToggleButton; +import com.android.services.telephony.common.AudioMode; + /** * Fragment for call control buttons */ public class CallButtonFragment extends BaseFragment - implements CallButtonPresenter.CallButtonUi { + implements CallButtonPresenter.CallButtonUi, OnMenuItemClickListener, + OnDismissListener { private ToggleButton mMuteButton; private ToggleButton mAudioButton; private ToggleButton mHoldButton; private ToggleButton mShowDialpadButton; + private PopupMenu mAudioModePopup; + private boolean mAudioModePopupVisible; private View mEndCallButton; @Override CallButtonPresenter createPresenter() { - return new CallButtonPresenter(); + // TODO: find a cleaner way to include audio mode provider than + // having a singleton instance. + return new CallButtonPresenter(AudioModeProvider.getInstance()); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - - final AudioManager audioManager = (AudioManager) getActivity().getSystemService( - Context.AUDIO_SERVICE); - getPresenter().init(audioManager); } @Override @@ -74,10 +83,10 @@ public class CallButtonFragment extends BaseFragment }); mAudioButton = (ToggleButton) parent.findViewById(R.id.audioButton); - mAudioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + mAudioButton.setOnClickListener(new View.OnClickListener() { @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - getPresenter().speakerClicked(isChecked); + public void onClick(View view) { + onAudioButtonClicked(); } }); @@ -103,6 +112,14 @@ public class CallButtonFragment extends BaseFragment @Override public void onViewCreated(View view, Bundle savedInstanceState) { getPresenter().onUiReady(this); + + // set the buttons + updateAudioButtons(getPresenter().getSupportedAudio()); + } + + @Override + public void onDestroyView() { + getPresenter().onUiUnready(this); } @Override @@ -119,17 +136,256 @@ public class CallButtonFragment extends BaseFragment mMuteButton.setChecked(value); } - /** - * TODO(klp): Rename this from setSpeaker() to setAudio() once it does more than speakerphone. - */ @Override - public void setSpeaker(boolean value) { - mAudioButton.setChecked(value); + public void setHold(boolean value) { + mHoldButton.setChecked(value); } @Override - public void setHold(boolean value) { - mHoldButton.setChecked(value); + public void setAudio(int mode) { + } + + @Override + public void setSupportedAudio(int modeMask) { + updateAudioButtons(modeMask); + refreshAudioModePopup(); + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + Logger.d(this, "- onMenuItemClick: " + item); + Logger.d(this, " id: " + item.getItemId()); + Logger.d(this, " title: '" + item.getTitle() + "'"); + + int mode = AudioMode.WIRED_OR_EARPIECE; + + switch (item.getItemId()) { + case R.id.audio_mode_speaker: + mode = AudioMode.SPEAKER; + break; + case R.id.audio_mode_earpiece: + case R.id.audio_mode_wired_headset: + // InCallAudioMode.EARPIECE means either the handset earpiece, + // or the wired headset (if connected.) + mode = AudioMode.WIRED_OR_EARPIECE; + break; + case R.id.audio_mode_bluetooth: + mode = AudioMode.BLUETOOTH; + break; + default: + Logger.e(this, "onMenuItemClick: unexpected View ID " + item.getItemId() + + " (MenuItem = '" + item + "')"); + break; + } + + getPresenter().setAudioMode(mode); + + return true; + } + + // PopupMenu.OnDismissListener implementation; see showAudioModePopup(). + // This gets called when the PopupMenu gets dismissed for *any* reason, like + // the user tapping outside its bounds, or pressing Back, or selecting one + // of the menu items. + @Override + public void onDismiss(PopupMenu menu) { + Logger.d(this, "- onDismiss: " + menu); + mAudioModePopupVisible = false; + } + + /** + * Checks for supporting modes. If bluetooth is supported, it uses the audio + * pop up menu. Otherwise, it toggles the speakerphone. + */ + private void onAudioButtonClicked() { + Logger.d(this, "onAudioButtonClicked: " + + AudioMode.toString(getPresenter().getSupportedAudio())); + + if (isSupported(AudioMode.BLUETOOTH)) { + showAudioModePopup(); + } else { + getPresenter().toggleSpeakerphone(); + } + } + + /** + * Refreshes the "Audio mode" popup if it's visible. This is useful + * (for example) when a wired headset is plugged or unplugged, + * since we need to switch back and forth between the "earpiece" + * and "wired headset" items. + * + * This is safe to call even if the popup is already dismissed, or even if + * you never called showAudioModePopup() in the first place. + */ + public void refreshAudioModePopup() { + if (mAudioModePopup != null && mAudioModePopupVisible) { + // Dismiss the previous one + mAudioModePopup.dismiss(); // safe even if already dismissed + // And bring up a fresh PopupMenu + showAudioModePopup(); + } + } + + /** + * Updates the audio button so that the appriopriate visual layers + * are visible based on the supported audio formats. + */ + private void updateAudioButtons(int supportedModes) { + final boolean bluetoothSupported = isSupported(AudioMode.BLUETOOTH); + final boolean speakerSupported = isSupported(AudioMode.SPEAKER); + + boolean audioButtonEnabled = false; + boolean audioButtonChecked = false; + boolean showMoreIndicator = false; + + boolean showBluetoothIcon = false; + boolean showSpeakerphoneOnIcon = false; + boolean showSpeakerphoneOffIcon = false; + boolean showHandsetIcon = false; + + boolean showToggleIndicator = false; + + if (bluetoothSupported) { + Logger.d(this, "updateAudioButtons - popup menu mode"); + + audioButtonEnabled = true; + showMoreIndicator = true; + // The audio button is NOT a toggle in this state. (And its + // setChecked() state is irrelevant since we completely hide the + // btn_compound_background layer anyway.) + + // Update desired layers: + if (isAudio(AudioMode.BLUETOOTH)) { + showBluetoothIcon = true; + } else if (isAudio(AudioMode.SPEAKER)) { + showSpeakerphoneOnIcon = true; + } else { + showHandsetIcon = true; + // TODO: if a wired headset is plugged in, that takes precedence + // over the handset earpiece. If so, maybe we should show some + // sort of "wired headset" icon here instead of the "handset + // earpiece" icon. (Still need an asset for that, though.) + } + } else if (speakerSupported) { + Logger.d(this, "updateAudioButtons - speaker toggle mode"); + + audioButtonEnabled = true; + + // The audio button *is* a toggle in this state, and indicated the + // current state of the speakerphone. + audioButtonChecked = isAudio(AudioMode.SPEAKER); + + // update desired layers: + showToggleIndicator = true; + + showSpeakerphoneOnIcon = isAudio(AudioMode.SPEAKER); + showSpeakerphoneOffIcon = !showSpeakerphoneOnIcon; + } else { + Logger.d(this, "updateAudioButtons - disabled..."); + + // The audio button is a toggle in this state, but that's mostly + // irrelevant since it's always disabled and unchecked. + audioButtonEnabled = false; + audioButtonChecked = false; + + // update desired layers: + showToggleIndicator = true; + showSpeakerphoneOffIcon = true; + } + + // Finally, update it all! + + Logger.v(this, "audioButtonEnabled: " + audioButtonEnabled); + Logger.v(this, "audioButtonChecked: " + audioButtonChecked); + Logger.v(this, "showMoreIndicator: " + showMoreIndicator); + Logger.v(this, "showBluetoothIcon: " + showBluetoothIcon); + Logger.v(this, "showSpeakerphoneOnIcon: " + showSpeakerphoneOnIcon); + Logger.v(this, "showSpeakerphoneOffIcon: " + showSpeakerphoneOffIcon); + Logger.v(this, "showHandsetIcon: " + showHandsetIcon); + + // Constants for Drawable.setAlpha() + final int HIDDEN = 0; + final int VISIBLE = 255; + + mAudioButton.setEnabled(audioButtonEnabled); + mAudioButton.setChecked(audioButtonChecked); + + final LayerDrawable layers = (LayerDrawable) mAudioButton.getBackground(); + Logger.d(this, "'layers' drawable: " + layers); + + layers.findDrawableByLayerId(R.id.compoundBackgroundItem) + .setAlpha(showToggleIndicator ? VISIBLE : HIDDEN); + + layers.findDrawableByLayerId(R.id.moreIndicatorItem) + .setAlpha(showMoreIndicator ? VISIBLE : HIDDEN); + + layers.findDrawableByLayerId(R.id.bluetoothItem) + .setAlpha(showBluetoothIcon ? VISIBLE : HIDDEN); + + layers.findDrawableByLayerId(R.id.handsetItem) + .setAlpha(showHandsetIcon ? VISIBLE : HIDDEN); + + layers.findDrawableByLayerId(R.id.speakerphoneOnItem) + .setAlpha(showSpeakerphoneOnIcon ? VISIBLE : HIDDEN); + + layers.findDrawableByLayerId(R.id.speakerphoneOffItem) + .setAlpha(showSpeakerphoneOffIcon ? VISIBLE : HIDDEN); + } + + private void showAudioModePopup() { + Logger.d(this, "showAudioPopup()..."); + + mAudioModePopup = new PopupMenu(getView().getContext(), mAudioButton /* anchorView */); + mAudioModePopup.getMenuInflater().inflate(R.menu.incall_audio_mode_menu, + mAudioModePopup.getMenu()); + mAudioModePopup.setOnMenuItemClickListener(this); + mAudioModePopup.setOnDismissListener(this); + + final Menu menu = mAudioModePopup.getMenu(); + + // TODO: Still need to have the "currently active" audio mode come + // up pre-selected (or focused?) with a blue highlight. Still + // need exact visual design, and possibly framework support for this. + // See comments below for the exact logic. + + final MenuItem speakerItem = menu.findItem(R.id.audio_mode_speaker); + speakerItem.setEnabled(isSupported(AudioMode.SPEAKER)); + // TODO: Show speakerItem as initially "selected" if + // speaker is on. + + // We display *either* "earpiece" or "wired headset", never both, + // depending on whether a wired headset is physically plugged in. + final MenuItem earpieceItem = menu.findItem(R.id.audio_mode_earpiece); + final MenuItem wiredHeadsetItem = menu.findItem(R.id.audio_mode_wired_headset); + + final boolean usingHeadset = isSupported(AudioMode.WIRED_HEADSET); + earpieceItem.setVisible(!usingHeadset); + earpieceItem.setEnabled(!usingHeadset); + wiredHeadsetItem.setVisible(usingHeadset); + wiredHeadsetItem.setEnabled(usingHeadset); + // TODO: Show the above item (either earpieceItem or wiredHeadsetItem) + // as initially "selected" if speakerOn and + // bluetoothIndicatorOn are both false. + + final MenuItem bluetoothItem = menu.findItem(R.id.audio_mode_bluetooth); + bluetoothItem.setEnabled(isSupported(AudioMode.BLUETOOTH)); + // TODO: Show bluetoothItem as initially "selected" if + // bluetoothIndicatorOn is true. + + mAudioModePopup.show(); + + // Unfortunately we need to manually keep track of the popup menu's + // visiblity, since PopupMenu doesn't have an isShowing() method like + // Dialogs do. + mAudioModePopupVisible = true; + } + + private boolean isSupported(int mode) { + return (mode == (getPresenter().getSupportedAudio() & mode)); + } + + private boolean isAudio(int mode) { + return (mode == getPresenter().getAudioMode()); } @Override diff --git a/InCallUI/src/com/android/incallui/CallButtonPresenter.java b/InCallUI/src/com/android/incallui/CallButtonPresenter.java index 35e6ab7f6..d4b2cf2de 100644 --- a/InCallUI/src/com/android/incallui/CallButtonPresenter.java +++ b/InCallUI/src/com/android/incallui/CallButtonPresenter.java @@ -20,28 +20,38 @@ import com.google.common.base.Preconditions; import android.media.AudioManager; +import com.android.incallui.AudioModeProvider.AudioModeListener; import com.android.incallui.InCallPresenter.InCallState; import com.android.incallui.InCallPresenter.InCallStateListener; +import com.android.services.telephony.common.AudioMode; import com.android.services.telephony.common.Call; /** * Logic for call buttons. */ public class CallButtonPresenter extends Presenter - implements InCallStateListener { + implements InCallStateListener, AudioModeListener { - private AudioManager mAudioManager; private Call mCall; + private final AudioModeProvider mAudioModeProvider; - public void init(AudioManager audioManager) { - mAudioManager = audioManager; + public CallButtonPresenter(AudioModeProvider audioModeProvider) { + + // AudioModeProvider works effectively as a pass through. However, if we + // had this presenter listen for changes directly, it would have to live forever + // or risk missing important updates. + mAudioModeProvider = audioModeProvider; + mAudioModeProvider.addListener(this); } @Override public void onUiReady(CallButtonUi ui) { super.onUiReady(ui); - getUi().setMute(mAudioManager.isMicrophoneMute()); - getUi().setSpeaker(mAudioManager.isSpeakerphoneOn()); + } + + @Override + public void onUiUnready(CallButtonUi ui) { + mAudioModeProvider.removeListener(this); } @Override @@ -55,23 +65,62 @@ public class CallButtonPresenter extends Presenter return inflater.inflate(R.layout.call_card, container, false); } + @Override public void onViewCreated(View view, Bundle savedInstanceState) { mPhoneNumber = (TextView) view.findViewById(R.id.phoneNumber); @@ -68,6 +69,11 @@ public class CallCardFragment extends BaseFragment getPresenter().onUiReady(this); } + @Override + public void onDestroyView() { + getPresenter().onUiUnready(this); + } + @Override public void setVisible(boolean on) { if (on) { diff --git a/InCallUI/src/com/android/incallui/CallCommandClient.java b/InCallUI/src/com/android/incallui/CallCommandClient.java index 80a9e9e10..8e0a16c46 100644 --- a/InCallUI/src/com/android/incallui/CallCommandClient.java +++ b/InCallUI/src/com/android/incallui/CallCommandClient.java @@ -88,9 +88,9 @@ public class CallCommandClient { } } - public void turnSpeakerOn(boolean onOff) { + public void setAudioMode(int mode) { try { - mCommandService.speaker(onOff); + mCommandService.setAudioMode(mode); } catch (RemoteException e) { Logger.e(this, "Error setting speaker.", e); } diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java index 173f6a345..8431fc91e 100644 --- a/InCallUI/src/com/android/incallui/CallHandlerService.java +++ b/InCallUI/src/com/android/incallui/CallHandlerService.java @@ -22,6 +22,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; +import com.android.services.telephony.common.AudioMode; import com.android.services.telephony.common.Call; import com.android.services.telephony.common.ICallCommandService; import com.android.services.telephony.common.ICallHandlerService; @@ -39,10 +40,14 @@ public class CallHandlerService extends Service { private static final int ON_UPDATE_CALL = 1; private static final int ON_UPDATE_MULTI_CALL = 2; private static final int ON_UPDATE_CALL_WITH_TEXT_RESPONSES = 3; + private static final int ON_AUDIO_MODE = 4; + private static final int ON_SUPPORTED_AUDIO_MODE = 5; + private CallList mCallList; private Handler mMainHandler; private InCallPresenter mInCallPresenter; + private AudioModeProvider mAudioModeProvider; @Override public void onCreate() { @@ -51,6 +56,7 @@ public class CallHandlerService extends Service { mCallList = CallList.getInstance(); mMainHandler = new MainHandler(); mInCallPresenter = InCallPresenter.init(this); + mAudioModeProvider = AudioModeProvider.getInstance(); } @Override @@ -66,12 +72,13 @@ public class CallHandlerService extends Service { @Override public void setCallCommandService(ICallCommandService service) { - Logger.d(this, "onConnected: " + service.toString()); + Logger.d(CallHandlerService.this, "onConnected: " + service.toString()); CallCommandClient.init(service); } @Override public void onDisconnect(Call call) { + Logger.d(CallHandlerService.this, "onDisconnected"); mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_CALL, 0, 0, call)); } @@ -86,16 +93,24 @@ public class CallHandlerService extends Service { @Override public void onUpdate(List calls, boolean fullUpdate) { + Logger.d(CallHandlerService.this, "onUpdate "); // TODO(klp): Add use of fullUpdate to message mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_MULTI_CALL, 0, 0, calls)); } @Override public void onAudioModeChange(int mode) { + Logger.d(CallHandlerService.this, "onAudioModeChange : " + AudioMode.toString(mode)); + mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_AUDIO_MODE, mode, 0, null)); } @Override - public void onAudioModeSupportChange(int modeMask) { + public void onSupportedAudioModeChange(int modeMask) { + Logger.d(CallHandlerService.this, "onSupportedAudioModeChange : " + + AudioMode.toString(modeMask)); + + mMainHandler.sendMessage( + mMainHandler.obtainMessage(ON_SUPPORTED_AUDIO_MODE, modeMask, 0, null)); } }; @@ -115,6 +130,8 @@ public class CallHandlerService extends Service { } private void executeMessage(Message msg) { + Logger.d(this, "executeMessage " + msg.what); + switch (msg.what) { case ON_UPDATE_CALL: mCallList.onUpdate((Call) msg.obj); @@ -125,6 +142,12 @@ public class CallHandlerService extends Service { case ON_UPDATE_CALL_WITH_TEXT_RESPONSES: mCallList.onUpdate((AbstractMap.SimpleEntry >) msg.obj); break; + case ON_AUDIO_MODE: + mAudioModeProvider.onAudioModeChange(msg.arg1); + break; + case ON_SUPPORTED_AUDIO_MODE: + mAudioModeProvider.onSupportedAudioModeChange(msg.arg1); + break; default: break; } diff --git a/InCallUI/src/com/android/incallui/Presenter.java b/InCallUI/src/com/android/incallui/Presenter.java index d4024d53f..b4962aea6 100644 --- a/InCallUI/src/com/android/incallui/Presenter.java +++ b/InCallUI/src/com/android/incallui/Presenter.java @@ -32,6 +32,13 @@ public abstract class Presenter { mUi = ui; } + /** + * Called when the UI view is destroyed in Fragment.onDestroyView(). + */ + public void onUiUnready(U ui) { + mUi = null; + } + public U getUi() { return mUi; } -- cgit v1.2.3