Merge "Temp work around for audio bugs" into master-nova
diff --git a/src/com/android/telecomm/Call.java b/src/com/android/telecomm/Call.java
index 96d8374..f40d4ea 100644
--- a/src/com/android/telecomm/Call.java
+++ b/src/com/android/telecomm/Call.java
@@ -23,6 +23,7 @@
import com.google.common.base.Preconditions;
import java.util.Date;
+import java.util.Locale;
import java.util.UUID;
/**
@@ -88,7 +89,8 @@
/** {@inheritDoc} */
@Override public String toString() {
- return "[" + mId + ", " + mState + ", " + mCallService.getComponentName() + "]";
+ return String.format(Locale.US, "[%s, %s, %s, %s]", mId, mState,
+ mCallService.getComponentName(), Log.pii(mHandle));
}
String getId() {
@@ -167,14 +169,14 @@
}
/**
- * Aborts ongoing attempts to connect this call. No-op once the call is connected or has been
- * disconnected. See {@link #disconnect} for already-connected calls.
+ * Aborts ongoing attempts to connect this call. Only applicable to {@link CallState#NEW}
+ * outgoing calls. See {@link #disconnect} for already-connected calls.
*/
void abort() {
- if (mState == CallState.NEW ||
- mState == CallState.DIALING ||
- mState == CallState.RINGING) {
-
+ if (mState == CallState.NEW) {
+ if (mCallService != null) {
+ mCallService.abort(mId);
+ }
clearCallService();
clearCallServiceSelector();
mState = CallState.ABORTED;
diff --git a/src/com/android/telecomm/CallServiceAdapter.java b/src/com/android/telecomm/CallServiceAdapter.java
index f602d50..8daa16e 100644
--- a/src/com/android/telecomm/CallServiceAdapter.java
+++ b/src/com/android/telecomm/CallServiceAdapter.java
@@ -46,9 +46,16 @@
/** Used to run code (e.g. messages, Runnables) on the main (UI) thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper());
- /** The set of pending incoming call IDs. Contains the call IDs for which we are expecting
- * details via {@link #handleIncomingCall}. If {@link #handleIncomingCall} is invoked for a call
- * ID that is not in this set, it will be ignored.
+ /**
+ * The set of pending outgoing call IDs. Any {@link #handleSuccessfulOutgoingCall} and
+ * {@link #handleFailedOutgoingCall} invocations with a call ID that is not in this set
+ * are ignored.
+ */
+ private final Set<String> mPendingOutgoingCallIds = Sets.newHashSet();
+
+ /**
+ * The set of pending incoming call IDs. Any {@link #handleIncomingCall} invocations with
+ * a call ID not in this set are ignored.
*/
private final Set<String> mPendingIncomingCallIds = Sets.newHashSet();
@@ -80,7 +87,7 @@
mIncomingCallsManager.handleSuccessfulIncomingCall(callInfo);
} else {
Log.wtf(CallServiceAdapter.this,
- "Received details for an unknown incoming call %s", callInfo);
+ "Unknown incoming call: %s", callInfo);
}
}
});
@@ -91,7 +98,13 @@
checkValidCallId(callId);
mHandler.post(new Runnable() {
@Override public void run() {
- mOutgoingCallsManager.handleSuccessfulCallAttempt(callId);
+ if (mPendingOutgoingCallIds.remove(callId)) {
+ mOutgoingCallsManager.handleSuccessfulCallAttempt(callId);
+ } else {
+ // TODO(gilad): Figure out how to wire up the callService.abort() call.
+ Log.wtf(CallServiceAdapter.this,
+ "Unknown outgoing call: %s", callId);
+ }
}
});
}
@@ -101,7 +114,12 @@
checkValidCallId(callId);
mHandler.post(new Runnable() {
@Override public void run() {
- mOutgoingCallsManager.handleFailedCallAttempt(callId, reason);
+ if (mPendingOutgoingCallIds.remove(callId)) {
+ mOutgoingCallsManager.handleFailedCallAttempt(callId, reason);
+ } else {
+ Log.wtf(CallServiceAdapter.this,
+ "Unknown outgoing call: %s", callId);
+ }
}
});
}
@@ -137,6 +155,8 @@
}
/** {@inheritDoc} */
+ // TODO(gilad): Ensure that any communication from the underlying ICallService
+ // implementation is expected (or otherwise suppressed at the adapter level).
@Override public void setDisconnected(final String callId) {
checkValidCallId(callId);
mHandler.post(new Runnable() {
@@ -147,6 +167,26 @@
}
/**
+ * Adds the specified call ID to the list of pending outgoing call IDs.
+ * TODO(gilad): Consider passing the call processor (instead of the ID) both here and in the
+ * remove case (same for incoming) such that the detour via the *CallsManager can be avoided.
+ *
+ * @param callId The ID of the call.
+ */
+ void addPendingOutgoingCallId(String callId) {
+ mPendingOutgoingCallIds.add(callId);
+ }
+
+ /**
+ * Removes the specified call ID from the list of pending outgoing call IDs.
+ *
+ * @param callId The ID of the call.
+ */
+ void removePendingOutgoingCallId(String callId) {
+ mPendingOutgoingCallIds.remove(callId);
+ }
+
+ /**
* Adds a call ID to the list of pending incoming call IDs. Only calls with call IDs in the
* list will be handled by {@link #handleIncomingCall}.
*
@@ -157,7 +197,7 @@
}
/**
- * Removed a call ID from the list of pending incoming call IDs.
+ * Removes the specified call ID from the list of pending incoming call IDs.
*
* @param callId The ID of the call.
*/
diff --git a/src/com/android/telecomm/CallServiceWrapper.java b/src/com/android/telecomm/CallServiceWrapper.java
index 94be7c8..15ec20d 100644
--- a/src/com/android/telecomm/CallServiceWrapper.java
+++ b/src/com/android/telecomm/CallServiceWrapper.java
@@ -24,6 +24,7 @@
import android.telecomm.CallServiceDescriptor;
import android.telecomm.ICallService;
import android.telecomm.ICallServiceAdapter;
+import android.telecomm.ICallServiceProvider;
/**
* Wrapper for {@link ICallService}s, handles binding to {@link ICallService} and keeps track of
@@ -92,11 +93,25 @@
/** See {@link ICallService#call}. */
public void call(CallInfo callInfo) {
+ String callId = callInfo.getId();
if (isServiceValid("call")) {
try {
mServiceInterface.call(callInfo);
+ mAdapter.addPendingOutgoingCallId(callId);
} catch (RemoteException e) {
- Log.e(this, e, "Failed to place call " + callInfo.getId() + ".");
+ Log.e(this, e, "Failed to place call " + callId + ".");
+ }
+ }
+ }
+
+ /** See {@link ICallService#abort}. */
+ public void abort(String callId) {
+ mAdapter.removePendingOutgoingCallId(callId);
+ if (isServiceValid("abort")) {
+ try {
+ mServiceInterface.abort(callId);
+ } catch (RemoteException e) {
+ Log.e(this, e, "Failed to abort call %s", callId);
}
}
}
diff --git a/src/com/android/telecomm/Log.java b/src/com/android/telecomm/Log.java
index 73892cd..f70cf55 100644
--- a/src/com/android/telecomm/Log.java
+++ b/src/com/android/telecomm/Log.java
@@ -18,6 +18,8 @@
import java.util.IllegalFormatException;
import java.util.Locale;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
/**
* Manages logging for the entire module.
@@ -118,6 +120,44 @@
android.util.Log.wtf(TAG, buildMessage(getPrefixFromObject(objectPrefix), format, args));
}
+ /**
+ * Redact personally identifiable information for production users.
+ * If we are running in verbose mode, return the original string, otherwise
+ * return a SHA-1 hash of the input string.
+ */
+ public static String pii(Object pii) {
+ if (pii == null || VERBOSE) {
+ return String.valueOf(pii);
+ }
+ return "[" + secureHash(String.valueOf(pii).getBytes()) + "]";
+ }
+
+ private static String secureHash(byte[] input) {
+ MessageDigest messageDigest;
+ try {
+ messageDigest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ messageDigest.update(input);
+ byte[] result = messageDigest.digest();
+ return encodeHex(result);
+ }
+
+ private static String encodeHex(byte[] bytes) {
+ StringBuffer hex = new StringBuffer(bytes.length * 2);
+
+ for (int i = 0; i < bytes.length; i++) {
+ int byteIntValue = (int) bytes[i] & 0xff;
+ if (byteIntValue < 0x10) {
+ hex.append("0");
+ }
+ hex.append(Integer.toString(byteIntValue, 16));
+ }
+
+ return hex.toString();
+ }
+
private static String getPrefixFromObject(Object obj) {
return obj == null ? "<null>" : obj.getClass().getSimpleName();
}
diff --git a/src/com/android/telecomm/OutgoingCallProcessor.java b/src/com/android/telecomm/OutgoingCallProcessor.java
index 42a16c6..4d21280 100644
--- a/src/com/android/telecomm/OutgoingCallProcessor.java
+++ b/src/com/android/telecomm/OutgoingCallProcessor.java
@@ -68,7 +68,7 @@
private final Map<String, CallServiceWrapper> mCallServicesById = Maps.newHashMap();
/**
- * The set of currently-available call-service selector implementations.
+ * The list of currently-available call-service selector implementations.
*/
private final List<ICallServiceSelector> mSelectors;
@@ -111,9 +111,6 @@
ThreadUtil.checkOnMainThread();
- Preconditions.checkNotNull(callServices);
- Preconditions.checkNotNull(selectors);
-
mCall = call;
mSelectors = selectors;
mOutgoingCallsManager = outgoingCallsManager;
@@ -132,17 +129,14 @@
* Initiates the attempt to place the call. No-op beyond the first invocation.
*/
void process() {
- ThreadUtil.checkOnMainThread();
+ if (!mIsAborted) {
+ // Only process un-aborted calls.
+ ThreadUtil.checkOnMainThread();
- if (mSelectors.isEmpty() || mCallServiceDescriptors.isEmpty()) {
- // TODO(gilad): Consider adding a failure message/type to differentiate the various
- // cases, or potentially throw an exception in this case.
- // TODO(gilad): Perform this check all the way up in switchboard to short-circuit
- // the current detour.
- mOutgoingCallsManager.handleFailedOutgoingCall(mCall);
- } else if (mSelectorIterator == null) {
- mSelectorIterator = mSelectors.iterator();
- attemptNextSelector();
+ if (mSelectorIterator == null) {
+ mSelectorIterator = mSelectors.iterator();
+ attemptNextSelector();
+ }
}
}
@@ -154,9 +148,6 @@
ThreadUtil.checkOnMainThread();
if (!mIsAborted) {
mCall.abort();
-
- // TODO(gilad): Add logic to notify the relevant call service and/or selector.
-
mIsAborted = true;
}
}
@@ -185,11 +176,13 @@
* @param reason The call-service supplied reason for the failed call attempt.
*/
void handleFailedCallAttempt(String reason) {
- ThreadUtil.checkOnMainThread();
+ if (!mIsAborted) {
+ ThreadUtil.checkOnMainThread();
- mCall.clearCallService();
- mCall.clearCallServiceSelector();
- attemptNextCallService();
+ mCall.clearCallService();
+ mCall.clearCallServiceSelector();
+ attemptNextCallService();
+ }
}
/**