diff options
Diffstat (limited to 'InCallUI')
5 files changed, 230 insertions, 19 deletions
diff --git a/InCallUI/src/com/android/incallui/CallCardFragment.java b/InCallUI/src/com/android/incallui/CallCardFragment.java index fb60c0b03..2fb317221 100644 --- a/InCallUI/src/com/android/incallui/CallCardFragment.java +++ b/InCallUI/src/com/android/incallui/CallCardFragment.java @@ -16,20 +16,47 @@ package com.android.incallui; -import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; /** * Fragment for call card. */ -public class CallCardFragment extends Fragment { +public class CallCardFragment extends BaseFragment<CallCardPresenter> + implements CallCardPresenter.CallCardUi { + + private TextView mPhoneNumber; + + @Override + CallCardPresenter createPresenter() { + return new CallCardPresenter(); + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.call_card_fragment, container, false); } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + mPhoneNumber = (TextView) view.findViewById(R.id.phoneNumber); + + // This method call will begin the callbacks on CallCardUi. We need to ensure + // everything needed for the callbacks is set up before this is called. + getPresenter().onUiReady(this); + } + + @Override + public void setNumber(String number) { + mPhoneNumber.setText(number); + } + + @Override + public void setName(String name) { + } + } diff --git a/InCallUI/src/com/android/incallui/CallCardPresenter.java b/InCallUI/src/com/android/incallui/CallCardPresenter.java new file mode 100644 index 000000000..85f05341e --- /dev/null +++ b/InCallUI/src/com/android/incallui/CallCardPresenter.java @@ -0,0 +1,55 @@ +/* + * 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.android.services.telephony.common.Call; + +/** + * Presenter for the Call Card Fragment. + * This class listens for changes to CallList and passes it along to the fragment. + */ +public class CallCardPresenter extends Presenter<CallCardPresenter.CallCardUi> + implements CallList.Listener { + + @Override + public void onUiReady(CallCardUi ui) { + super.onUiReady(ui); + + CallList.getInstance().addListener(this); + + // When UI is ready, manually trigger a change + onCallListChange(CallList.getInstance()); + } + + @Override + public void onCallListChange(CallList callList) { + Call call = callList.getIncomingOrActive(); + + if (call != null) { + getUi().setNumber(call.getNumber()); + } else { + // When there is no longer an incoming/active call, we need to reset everything + // so that no data survives for the next call. + getUi().setNumber(""); + } + } + + public interface CallCardUi extends Ui { + public void setNumber(String number); + public void setName(String name); + } +} diff --git a/InCallUI/src/com/android/incallui/CallHandlerService.java b/InCallUI/src/com/android/incallui/CallHandlerService.java index 127e57513..4a14dab8e 100644 --- a/InCallUI/src/com/android/incallui/CallHandlerService.java +++ b/InCallUI/src/com/android/incallui/CallHandlerService.java @@ -18,7 +18,9 @@ package com.android.incallui; import android.app.Service; import android.content.Intent; +import android.os.Handler; import android.os.IBinder; +import android.os.Message; import android.util.Log; import com.android.services.telephony.common.Call; @@ -35,13 +37,18 @@ public class CallHandlerService extends Service { private static final String TAG = CallHandlerService.class.getSimpleName(); private static final boolean DBG = false; // TODO: Have a shared location for this. + private static final int ON_UPDATE_CALL = 1; + private static final int ON_UPDATE_MULTI_CALL = 2; + private CallList mCallList; + private Handler mMainHandler; @Override public void onCreate() { super.onCreate(); - mCallList = new CallList(); + mCallList = CallList.getInstance(); + mMainHandler = new MainHandler(); } @Override @@ -63,21 +70,21 @@ public class CallHandlerService extends Service { @Override public void onIncomingCall(Call call) { - mCallList.onUpdate(call); - final Intent intent = new Intent(getApplication(), InCallActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); + + mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_CALL, 0, 0, call)); } @Override public void onDisconnect(Call call) { - mCallList.onUpdate(call); + mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_CALL, 0, 0, call)); } @Override public void onUpdate(List<Call> calls) { - mCallList.onUpdate(calls); + mMainHandler.sendMessage(mMainHandler.obtainMessage(ON_UPDATE_MULTI_CALL, 0, 0, calls)); } }; @@ -86,4 +93,32 @@ public class CallHandlerService extends Service { Log.d(TAG, message); } } + + /** + * Handles messages from the service so that they get executed on the main thread, where they + * can interact with UI. + */ + private class MainHandler extends Handler { + MainHandler() { + super(getApplicationContext().getMainLooper(), null, true); + } + + @Override + public void handleMessage(Message msg) { + executeMessage(msg); + } + } + + private void executeMessage(Message msg) { + switch (msg.what) { + case ON_UPDATE_CALL: + mCallList.onUpdate((Call) msg.obj); + break; + case ON_UPDATE_MULTI_CALL: + mCallList.onUpdate((List<Call>) msg.obj); + break; + default: + break; + } + } } diff --git a/InCallUI/src/com/android/incallui/CallList.java b/InCallUI/src/com/android/incallui/CallList.java index 5fe261946..ac3e3bfd5 100644 --- a/InCallUI/src/com/android/incallui/CallList.java +++ b/InCallUI/src/com/android/incallui/CallList.java @@ -16,14 +16,19 @@ package com.android.incallui; +import com.google.android.collect.Lists; import com.google.android.collect.Maps; +import com.google.android.collect.Sets; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; +import android.util.Log; + import com.android.services.telephony.common.Call; import java.util.HashMap; import java.util.List; +import java.util.Set; /** * Maintains the list of active calls received from CallHandlerService. @@ -31,18 +36,89 @@ import java.util.List; * changes to calls. */ public class CallList { + private static String TAG = CallList.class.getSimpleName(); + + private static CallList sInstance; + + private final HashMap<Integer, Call> mCallMap = Maps.newHashMap(); + private final Set<Listener> mListeners = Sets.newArraySet(); + + /** + * Static singleton accessor method. + */ + public static synchronized CallList getInstance() { + if (sInstance == null) { + sInstance = new CallList(); + } + return sInstance; + } - final HashMap<Integer, Call> callMap = Maps.newHashMap(); + /** + * Private constructor. Instance should only be acquired through getInstance(). + */ + private CallList() { + } + /** + * Called when a single call has changed. + */ public void onUpdate(Call call) { updateCallInMap(call); + + notifyListenersOfChange(); } + /** + * Called when multiple calls have changed. + */ public void onUpdate(List<Call> callsToUpdate) { Preconditions.checkNotNull(callsToUpdate); for (Call call : callsToUpdate) { updateCallInMap(call); } + + notifyListenersOfChange(); + } + + public void addListener(Listener listener) { + Preconditions.checkNotNull(listener); + mListeners.add(listener); + } + + public void removeListener(Listener listener) { + Preconditions.checkNotNull(listener); + mListeners.remove(listener); + } + + /** + * TODO(klp): Change so that this function is not needed. Instead of assuming there is an active + * call, the code should rely on the status of a specific Call and allow the presenters to + * update the Call object when the active call changes. + */ + public Call getIncomingOrActive() { + Call retval = null; + + for (Call call : mCallMap.values()) { + if (call.getState() == Call.State.INCOMING) { + retval = call; + // incoming call takes precedence, cut out early. + break; + } else if (retval == null && call.getState() == Call.State.ACTIVE) { + retval = call; + } + } + + return retval; + } + + /** + * Sends a generic notification to all listeners that something has changed. + * It is up to the listeners to call back to determine what changed. + */ + private void notifyListenersOfChange() { + for (Listener listener : mListeners) { + listener.onCallListChange(this); + } } private void updateCallInMap(Call call) { @@ -50,15 +126,23 @@ public class CallList { final Integer id = new Integer(call.getCallId()); - if (isCallActive(call)) { - callMap.put(id, call); - } else if (callMap.containsKey(id)) { - callMap.remove(id); + if (!isCallDead(call)) { + mCallMap.put(id, call); + } else if (mCallMap.containsKey(id)) { + mCallMap.remove(id); } } - private boolean isCallActive(Call call) { + private boolean isCallDead(Call call) { final int state = call.getState(); - return Call.State.IDLE != state && Call.State.INVALID != state; + return Call.State.IDLE == state || Call.State.INVALID == state; + } + + /** + * Listener interface for any class that wants to be notified of changes + * to the call list. + */ + public interface Listener { + public void onCallListChange(CallList callList); } } diff --git a/InCallUI/src/com/android/incallui/InCallActivity.java b/InCallUI/src/com/android/incallui/InCallActivity.java index 71e981b94..04f1f09b1 100644 --- a/InCallUI/src/com/android/incallui/InCallActivity.java +++ b/InCallUI/src/com/android/incallui/InCallActivity.java @@ -38,6 +38,7 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); private CallButtonPresenter mCallButtonPresenter; + private CallCardPresenter mCallCardPresenter; @Override protected void onCreate(Bundle icicle) { @@ -57,6 +58,8 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC // Inflate everything in incall_screen.xml and add it to the screen. setContentView(R.layout.incall_screen); + initializeInCall(); + logD("onCreate(): exit"); } @@ -65,11 +68,6 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC protected void onResume() { logD("onResume()..."); - final CallButtonFragment callButtonFragment = (CallButtonFragment) getFragmentManager() - .findFragmentById(R.id.callButtonFragment); - mCallButtonPresenter = callButtonFragment.getPresenter(); - mCallButtonPresenter.setEndCallListener(this); - // TODO(klp): create once and reset when needed. final AnswerFragment answerFragment = new AnswerFragment(); final AnswerPresenter presenter = answerFragment.getPresenter(); @@ -207,8 +205,20 @@ public class InCallActivity extends Activity implements CallButtonPresenter.EndC return super.onKeyDown(keyCode, event); } + private void initializeInCall() { + + final CallButtonFragment callButtonFragment = (CallButtonFragment) getFragmentManager() + .findFragmentById(R.id.callButtonFragment); + mCallButtonPresenter = callButtonFragment.getPresenter(); + mCallButtonPresenter.setEndCallListener(this); + + final CallCardFragment callCardFragment = (CallCardFragment) getFragmentManager() + .findFragmentById(R.id.callCardFragment); + } + private void toast(String text) { final Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT); + toast.show(); } |