summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/values-da/strings.xml6
-rw-r--r--res/values-mr/strings.xml4
-rw-r--r--res/values-pa/strings.xml2
-rw-r--r--res/xml/layout_blocked_number.xml4
-rw-r--r--src/com/android/server/telecom/Call.java92
-rw-r--r--src/com/android/server/telecom/CallsManager.java29
-rw-r--r--src/com/android/server/telecom/ClockProxy.java39
-rw-r--r--src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java24
-rw-r--r--src/com/android/server/telecom/TelecomSystem.java7
-rw-r--r--src/com/android/server/telecom/components/TelecomService.java16
-rw-r--r--tests/src/com/android/server/telecom/tests/BasicCallTests.java29
-rw-r--r--tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java4
-rw-r--r--tests/src/com/android/server/telecom/tests/TelecomSystemTest.java26
13 files changed, 221 insertions, 61 deletions
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index ca762e02..2e0ed396 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -52,13 +52,13 @@
<string name="blocked_numbers" msgid="2751843139572970579">"Blokerede telefonnumre"</string>
<string name="blocked_numbers_msg" msgid="1045015186124965643">"Du modtager ikke opkald og sms-beskeder fra blokerede numre."</string>
<string name="block_number" msgid="1101252256321306179">"Tilføj et nummer"</string>
- <string name="unblock_dialog_body" msgid="1614238499771862793">"Vil du ophæve blokeringen af <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
- <string name="unblock_button" msgid="3078048901972674170">"Ophæv blokeringen"</string>
+ <string name="unblock_dialog_body" msgid="1614238499771862793">"Vil du fjerne blokeringen af <xliff:g id="NUMBER_TO_BLOCK">%1$s</xliff:g>?"</string>
+ <string name="unblock_button" msgid="3078048901972674170">"Fjern blokeringen"</string>
<string name="add_blocked_dialog_body" msgid="9030243212265516828">"Bloker opkald og sms-beskeder fra"</string>
<string name="add_blocked_number_hint" msgid="6847675097085433553">"Telefonnummer"</string>
<string name="block_button" msgid="8822290682524373357">"Bloker"</string>
<string name="non_primary_user" msgid="5180129233352533459">"Det er kun ejeren af en enhed, der kan se og administrere blokerede numre."</string>
- <string name="delete_icon_description" msgid="8903995728252556724">"Ophæv blokering"</string>
+ <string name="delete_icon_description" msgid="8903995728252556724">"Fjern blokering"</string>
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"Blokering er midlertidigt slået fra"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"Når du har ringet eller sendt en sms-besked til alarmcentralen, bliver blokering slået fra for at sikre, at alarmcentralen kan komme i kontakt med dig."</string>
<string name="blocked_numbers_butter_bar_button" msgid="2197943354922010696">"Genaktiver nu"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index a061027b..aafe222a 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -39,7 +39,7 @@
<string name="respond_via_sms_confirmation_format" msgid="7229149977515784269">"संदेश <xliff:g id="PHONE_NUMBER">%s</xliff:g> वर पाठविला."</string>
<string name="enable_account_preference_title" msgid="2021848090086481720">"कॉल करण्याची खाती"</string>
<string name="outgoing_call_not_allowed_user_restriction" msgid="6872406278300131364">"फक्त आणीबाणी कॉल करण्याची परवानगी आहे."</string>
- <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"हा अनुप्रयोग फोन परवानगी शिवाय कॉल करू शकत नाही."</string>
+ <string name="outgoing_call_not_allowed_no_permission" msgid="1996571596464271228">"हा अॅप्लिकेशन फोन परवानगी शिवाय कॉल करू शकत नाही."</string>
<string name="outgoing_call_error_no_phone_number_supplied" msgid="1940125199802007505">"कॉल करण्यासाठी, एक वैध नंबर प्रविष्ट करा."</string>
<string name="duplicate_video_call_not_allowed" msgid="3749211605014548386">"यावेळी कॉल जोडला जाऊ शकत नाही."</string>
<string name="no_vm_number" msgid="4164780423805688336">"व्हॉइसमेल नंबर गहाळ"</string>
@@ -57,7 +57,7 @@
<string name="add_blocked_dialog_body" msgid="9030243212265516828">"यावरील कॉल आणि मजकूर अवरोधित करा"</string>
<string name="add_blocked_number_hint" msgid="6847675097085433553">"फोन नंबर"</string>
<string name="block_button" msgid="8822290682524373357">"अवरोधित करा"</string>
- <string name="non_primary_user" msgid="5180129233352533459">"फक्त डीव्हाइस मालक अवरोधित केलेले नंबर पाहू आणि व्यवस्थापित करू शकतो."</string>
+ <string name="non_primary_user" msgid="5180129233352533459">"फक्त डिव्हाइस मालक अवरोधित केलेले नंबर पाहू आणि व्यवस्थापित करू शकतो."</string>
<string name="delete_icon_description" msgid="8903995728252556724">"अनावरोधित करा"</string>
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"अवरोधित करणे तात्पुरते बंद आहे"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"आपण एखादा आणीबाणी नंबर डायल केला किंवा त्यावर मजकूर पाठविल्यानंतर, आणीबाणी सेवा आपल्याशी संपर्क साधू शकतात हे सुनिश्चित करण्यासाठी अवरोधित करणे बंद करते."</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 18f69b2d..5bf26f3b 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -57,7 +57,7 @@
<string name="add_blocked_dialog_body" msgid="9030243212265516828">"ਇਸ ਨੰਬਰ ਤੋਂ ਕਾਲਾਂ ਅਤੇ ਲਿਖਤੀ ਸੁਨੇਹਿਆਂ ਨੂੰ ਬਲੌਕ ਕਰੋ"</string>
<string name="add_blocked_number_hint" msgid="6847675097085433553">"ਫ਼ੋਨ ਨੰਬਰ"</string>
<string name="block_button" msgid="8822290682524373357">"ਬਲੌਕ ਕਰੋ"</string>
- <string name="non_primary_user" msgid="5180129233352533459">"ਸਿਰਫ਼ ਡੀਵਾਈਸ ਮਾਲਕ ਹੀ ਬਲੌਕ ਕੀਤੇ ਗਏ ਨੰਬਰਾਂ ਨੂੰ ਵੇਖ ਅਤੇ ਪ੍ਰਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <string name="non_primary_user" msgid="5180129233352533459">"ਸਿਰਫ਼ ਡੀਵਾਈਸ ਮਾਲਕ ਹੀ ਬਲੌਕ ਕੀਤੇ ਗਏ ਨੰਬਰਾਂ ਨੂੰ ਦੇਖ ਅਤੇ ਪ੍ਰਬੰਧਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
<string name="delete_icon_description" msgid="8903995728252556724">"ਅਨਬਲੌਕ ਕਰੋ"</string>
<string name="blocked_numbers_butter_bar_title" msgid="438170866438793182">"ਬਲੌਕਿੰਗ ਆਰਜ਼ੀ ਤੌਰ \'ਤੇ ਬੰਦ ਹੈ"</string>
<string name="blocked_numbers_butter_bar_body" msgid="2223244484319442431">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਇੱਕ ਐਮਰਜੈਂਸੀ ਨੰਬਰ ਨੂੰ ਡਾਇਲ ਕੀਤੇ ਜਾਣ ਜਾਂ ਲਿਖਤ ਸੁਨੇਹਾ ਭੇਜੇ ਜਾਣ ਤੋਂ ਬਾਅਦ, ਇਹ ਯਕੀਨੀ ਬਣਾਉਣ ਲਈ ਬਲੌਕਿੰਗ ਨੂੰ ਬੰਦ ਕੀਤਾ ਜਾਂਦਾ ਹੈ ਕਿ ਐਮਰਜੈਂਸੀ ਸੇਵਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਪਰਕ ਕਰ ਸਕਣ।"</string>
diff --git a/res/xml/layout_blocked_number.xml b/res/xml/layout_blocked_number.xml
index 94cdbae0..fbd7de3d 100644
--- a/res/xml/layout_blocked_number.xml
+++ b/res/xml/layout_blocked_number.xml
@@ -28,8 +28,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
- android:layout_toStartOf="@+id/delete_blocked_number"
- android:paddingTop="@dimen/blocked_numbers_delete_icon_padding" />
+ android:paddingTop="@dimen/blocked_numbers_delete_icon_padding"
+ android:textDirection="ltr" />
<ImageView
android:id="@+id/delete_blocked_number"
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
index 9ab52900..90c1fe81 100644
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -27,6 +27,7 @@ import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.provider.ContactsContract.Contacts;
import android.telecom.CallAudioState;
@@ -242,17 +243,38 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
private String mViaNumber = "";
/**
- * The time this call was created. Beyond logging and such, may also be used for bookkeeping
- * and specifically for marking certain call attempts as failed attempts.
+ * The wall clock time this call was created. Beyond logging and such, may also be used for
+ * bookkeeping and specifically for marking certain call attempts as failed attempts.
+ * Note: This timestamp should NOT be used for calculating call duration.
*/
- private long mCreationTimeMillis = System.currentTimeMillis();
+ private long mCreationTimeMillis;
/** The time this call was made active. */
private long mConnectTimeMillis = 0;
- /** The time this call was disconnected. */
+ /**
+ * The time, in millis, since boot when this call was connected. This should ONLY be used when
+ * calculating the duration of the call.
+ *
+ * The reason for this is that the {@link SystemClock#elapsedRealtime()} is based on the
+ * elapsed time since the device was booted. Changes to the system clock (e.g. due to NITZ
+ * time sync, time zone changes user initiated clock changes) would cause a duration calculated
+ * based on {@link #mConnectTimeMillis} to change based on the delta in the time.
+ * Using the {@link SystemClock#elapsedRealtime()} ensures that changes to the wall clock do
+ * not impact the call duration.
+ */
+ private long mConnectElapsedTimeMillis = 0;
+
+ /** The wall clock time this call was disconnected. */
private long mDisconnectTimeMillis = 0;
+ /**
+ * The elapsed time since boot when this call was disconnected. Recorded as the
+ * {@link SystemClock#elapsedRealtime()}. This ensures that the call duration is not impacted
+ * by changes in the wall time clock.
+ */
+ private long mDisconnectElapsedTimeMillis = 0;
+
/** The gateway information associated with this call. This stores the original call handle
* that the user is attempting to connect to via the gateway, the actual handle to dial in
* order to connect the call via the gateway, as well as the package name of the gateway
@@ -376,6 +398,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
private final ConnectionServiceRepository mRepository;
private final Context mContext;
private final CallsManager mCallsManager;
+ private final ClockProxy mClockProxy;
private final TelecomSystem.SyncRoot mLock;
private final String mId;
private String mConnectionId;
@@ -471,20 +494,19 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
/**
* Persists the specified parameters and initializes the new instance.
- *
- * @param context The context.
+ * @param context The context.
* @param repository The connection service repository.
* @param handle The handle to dial.
* @param gatewayInfo Gateway information to use for the call.
* @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
- * This account must be one that was registered with the
- * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
+* This account must be one that was registered with the
+* {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
* @param targetPhoneAccountHandle Account information to use for the call. This account must be
- * one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
+* one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
* @param callDirection one of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING,
- * or CALL_DIRECTION_UNKNOWN.
+* or CALL_DIRECTION_UNKNOWN.
* @param shouldAttachToExistingConnection Set to true to attach the call to an existing
- * connection, regardless of whether it's incoming or outgoing.
+ * @param clockProxy
*/
public Call(
String callId,
@@ -501,7 +523,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
PhoneAccountHandle targetPhoneAccountHandle,
int callDirection,
boolean shouldAttachToExistingConnection,
- boolean isConference) {
+ boolean isConference,
+ ClockProxy clockProxy) {
mId = callId;
mConnectionId = callId;
mState = isConference ? CallState.ACTIVE : CallState.NEW;
@@ -522,26 +545,27 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
|| callDirection == CALL_DIRECTION_INCOMING;
maybeLoadCannedSmsResponses();
mAnalytics = new Analytics.CallInfo();
-
+ mClockProxy = clockProxy;
+ mCreationTimeMillis = mClockProxy.currentTimeMillis();
}
/**
* Persists the specified parameters and initializes the new instance.
- *
- * @param context The context.
+ * @param context The context.
* @param repository The connection service repository.
* @param handle The handle to dial.
* @param gatewayInfo Gateway information to use for the call.
* @param connectionManagerPhoneAccountHandle Account to use for the service managing the call.
- * This account must be one that was registered with the
- * {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
+* This account must be one that was registered with the
+* {@link PhoneAccount#CAPABILITY_CONNECTION_MANAGER} flag.
* @param targetPhoneAccountHandle Account information to use for the call. This account must be
- * one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
+* one that was registered with the {@link PhoneAccount#CAPABILITY_CALL_PROVIDER} flag.
* @param callDirection one of CALL_DIRECTION_INCOMING, CALL_DIRECTION_OUTGOING,
- * or CALL_DIRECTION_UNKNOWN
+* or CALL_DIRECTION_UNKNOWN
* @param shouldAttachToExistingConnection Set to true to attach the call to an existing
- * connection, regardless of whether it's incoming or outgoing.
+* connection, regardless of whether it's incoming or outgoing.
* @param connectTimeMillis The connection time of the call.
+ * @param clockProxy
*/
Call(
String callId,
@@ -559,13 +583,16 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
int callDirection,
boolean shouldAttachToExistingConnection,
boolean isConference,
- long connectTimeMillis) {
+ long connectTimeMillis,
+ long connectElapsedTimeMillis,
+ ClockProxy clockProxy) {
this(callId, context, callsManager, lock, repository, contactsAsyncHelper,
callerInfoAsyncQueryFactory, phoneNumberUtilsAdapter, handle, gatewayInfo,
connectionManagerPhoneAccountHandle, targetPhoneAccountHandle, callDirection,
- shouldAttachToExistingConnection, isConference);
+ shouldAttachToExistingConnection, isConference, clockProxy);
mConnectTimeMillis = connectTimeMillis;
+ mConnectElapsedTimeMillis = connectElapsedTimeMillis;
mAnalytics.setCallStartTime(connectTimeMillis);
}
@@ -790,14 +817,17 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
// We check to see if mConnectTime is already set to prevent the
// call from resetting active time when it goes in and out of
// ACTIVE/ON_HOLD
- mConnectTimeMillis = System.currentTimeMillis();
+ mConnectTimeMillis = mClockProxy.currentTimeMillis();
+ mConnectElapsedTimeMillis = mClockProxy.elapsedRealtime();
mAnalytics.setCallStartTime(mConnectTimeMillis);
}
// We're clearly not disconnected, so reset the disconnected time.
mDisconnectTimeMillis = 0;
+ mDisconnectElapsedTimeMillis = 0;
} else if (mState == CallState.DISCONNECTED) {
- mDisconnectTimeMillis = System.currentTimeMillis();
+ mDisconnectTimeMillis = mClockProxy.currentTimeMillis();
+ mDisconnectElapsedTimeMillis = mClockProxy.elapsedRealtime();
mAnalytics.setCallEndTime(mDisconnectTimeMillis);
setLocallyDisconnecting(false);
fixParentAfterDisconnect();
@@ -1200,9 +1230,11 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
}
/**
+ * Note: This method relies on {@link #mConnectElapsedTimeMillis} and
+ * {@link #mDisconnectElapsedTimeMillis} which are independent of the wall clock (which could
+ * change due to clock changes).
* @return The "age" of this call object in milliseconds, which typically also represents the
- * period since this call was added to the set pending outgoing calls, see
- * mCreationTimeMillis.
+ * period since this call was added to the set pending outgoing calls.
*/
@VisibleForTesting
public long getAgeMillis() {
@@ -1211,16 +1243,16 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable {
mDisconnectCause.getCode() == DisconnectCause.MISSED)) {
// Rejected and missed calls have no age. They're immortal!!
return 0;
- } else if (mConnectTimeMillis == 0) {
+ } else if (mConnectElapsedTimeMillis == 0) {
// Age is measured in the amount of time the call was active. A zero connect time
// indicates that we never went active, so return 0 for the age.
return 0;
- } else if (mDisconnectTimeMillis == 0) {
+ } else if (mDisconnectElapsedTimeMillis == 0) {
// We connected, but have not yet disconnected
- return System.currentTimeMillis() - mConnectTimeMillis;
+ return mClockProxy.elapsedRealtime() - mConnectElapsedTimeMillis;
}
- return mDisconnectTimeMillis - mConnectTimeMillis;
+ return mDisconnectElapsedTimeMillis - mConnectElapsedTimeMillis;
}
/**
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index c44e4fab..6cb08b2b 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -257,6 +257,7 @@ public class CallsManager extends Call.ListenerBase
private final DefaultDialerCache mDefaultDialerCache;
private final Timeouts.Adapter mTimeoutsAdapter;
private final PhoneNumberUtilsAdapter mPhoneNumberUtilsAdapter;
+ private final ClockProxy mClockProxy;
private final Set<Call> mLocallyDisconnectingCalls = new HashSet<>();
private final Set<Call> mPendingCallsToDisconnect = new HashSet<>();
/* Handler tied to thread in which CallManager was initialized. */
@@ -306,7 +307,8 @@ public class CallsManager extends Call.ListenerBase
AsyncRingtonePlayer asyncRingtonePlayer,
PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
EmergencyCallHelper emergencyCallHelper,
- InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory) {
+ InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
+ ClockProxy clockProxy) {
mContext = context;
mLock = lock;
mPhoneNumberUtilsAdapter = phoneNumberUtilsAdapter;
@@ -370,6 +372,7 @@ public class CallsManager extends Call.ListenerBase
mConnectionServiceRepository =
new ConnectionServiceRepository(mPhoneAccountRegistrar, mContext, mLock, this);
mInCallWakeLockController = inCallWakeLockControllerFactory.create(context, this);
+ mClockProxy = clockProxy;
mListeners.add(mInCallWakeLockController);
mListeners.add(statusBarNotifier);
@@ -833,8 +836,8 @@ public class CallsManager extends Call.ListenerBase
phoneAccountHandle,
Call.CALL_DIRECTION_INCOMING /* callDirection */,
false /* forceAttachToExistingConnection */,
- false /* isConference */
- );
+ false, /* isConference */
+ mClockProxy);
// Ensure new calls related to self-managed calls/connections are set as such. This will
// be overridden when the actual connection is returned in startCreateConnection, however
@@ -967,8 +970,8 @@ public class CallsManager extends Call.ListenerBase
// Use onCreateIncomingConnection in TelephonyConnectionService, so that we attach
// to the existing connection instead of trying to create a new one.
true /* forceAttachToExistingConnection */,
- false /* isConference */
- );
+ false, /* isConference */
+ mClockProxy);
call.initAnalytics();
setIntentExtrasAndStartTime(call, extras);
@@ -1047,8 +1050,8 @@ public class CallsManager extends Call.ListenerBase
null /* phoneAccountHandle */,
Call.CALL_DIRECTION_OUTGOING /* callDirection */,
false /* forceAttachToExistingConnection */,
- false /* isConference */
- );
+ false, /* isConference */
+ mClockProxy);
call.initAnalytics();
// Ensure new calls related to self-managed calls/connections are set as such. This
@@ -2023,6 +2026,10 @@ public class CallsManager extends Call.ListenerBase
parcelableConference.getConnectTimeMillis() ==
Conference.CONNECT_TIME_NOT_SPECIFIED ? 0 :
parcelableConference.getConnectTimeMillis();
+ long connectElapsedTime =
+ parcelableConference.getConnectElapsedTimeMillis() ==
+ Conference.CONNECT_TIME_NOT_SPECIFIED ? 0 :
+ parcelableConference.getConnectElapsedTimeMillis();
Call call = new Call(
callId,
@@ -2040,7 +2047,9 @@ public class CallsManager extends Call.ListenerBase
Call.CALL_DIRECTION_UNDEFINED /* callDirection */,
false /* forceAttachToExistingConnection */,
true /* isConference */,
- connectTime);
+ connectTime,
+ connectElapsedTime,
+ mClockProxy);
setCallState(call, Call.getStateFromConnectionState(parcelableConference.getState()),
"new conference call");
@@ -2707,7 +2716,9 @@ public class CallsManager extends Call.ListenerBase
Call.CALL_DIRECTION_UNDEFINED /* callDirection */,
false /* forceAttachToExistingConnection */,
isDowngradedConference /* isConference */,
- connection.getConnectTimeMillis() /* connectTimeMillis */);
+ connection.getConnectTimeMillis() /* connectTimeMillis */,
+ connection.getConnectElapsedTimeMillis(), /* connectElapsedTimeMillis */
+ mClockProxy);
call.initAnalytics();
call.getAnalytics().setCreatedFromExistingConnection(true);
diff --git a/src/com/android/server/telecom/ClockProxy.java b/src/com/android/server/telecom/ClockProxy.java
new file mode 100644
index 00000000..6f92f947
--- /dev/null
+++ b/src/com/android/server/telecom/ClockProxy.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.server.telecom;
+
+import android.os.SystemClock;
+
+/**
+ * Defines common clock functionality used in Telecom. Provided to make unit testing of clock
+ * operations testable.
+ */
+public interface ClockProxy {
+ /**
+ * Returns the current wall-clock time of the system, as typically returned by
+ * {@link System#currentTimeMillis()}.
+ * @return The current wall-clock time.
+ */
+ long currentTimeMillis();
+
+ /**
+ * Returns the elapsed time since boot of the system, as typically returned by
+ * {@link SystemClock#elapsedRealtime()}.
+ * @return the current elapsed real time.
+ */
+ long elapsedRealtime();
+}
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index 74ee668d..c592fcd1 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -30,6 +30,7 @@ import android.os.UserHandle;
import android.telecom.GatewayInfo;
import android.telecom.Log;
import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.DisconnectCause;
@@ -269,6 +270,21 @@ public class NewOutgoingCallIntentBroadcaster {
return DisconnectCause.INVALID_NUMBER;
}
+ // True for all managed calls, false for self-managed calls.
+ boolean sendNewOutgoingCallBroadcast = true;
+ PhoneAccountHandle targetPhoneAccount = mIntent.getParcelableExtra(
+ TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+ if (targetPhoneAccount != null) {
+ PhoneAccount phoneAccount =
+ mCallsManager.getPhoneAccountRegistrar().getPhoneAccountUnchecked(
+ targetPhoneAccount);
+ if (phoneAccount != null && phoneAccount.isSelfManaged()) {
+ callImmediately = true;
+ sendNewOutgoingCallBroadcast = false;
+ Log.i(this, "Skipping NewOutgoingCallBroadcast for self-managed call.");
+ }
+ }
+
if (callImmediately) {
Log.i(this, "Placing call immediately instead of waiting for "
+ " OutgoingCallBroadcastReceiver: %s", intent);
@@ -287,9 +303,11 @@ public class NewOutgoingCallIntentBroadcaster {
// initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra.
}
- UserHandle targetUser = mCall.getInitiatingUser();
- Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
- broadcastIntent(intent, number, !callImmediately, targetUser);
+ if (sendNewOutgoingCallBroadcast) {
+ UserHandle targetUser = mCall.getInitiatingUser();
+ Log.i(this, "Sending NewOutgoingCallBroadcast for %s to %s", mCall, targetUser);
+ broadcastIntent(intent, number, !callImmediately, targetUser);
+ }
return DisconnectCause.NOT_DISCONNECTED;
}
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index b40381bb..31afbba6 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -22,7 +22,6 @@ import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.components.UserCallIntentProcessorFactory;
import com.android.server.telecom.ui.IncomingCallNotifier;
-import com.android.server.telecom.ui.IncomingCallNotifier.IncomingCallNotifierFactory;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
@@ -190,7 +189,8 @@ public class TelecomSystem {
AsyncRingtonePlayer asyncRingtonePlayer,
PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
IncomingCallNotifier incomingCallNotifier,
- InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory) {
+ InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
+ ClockProxy clockProxy) {
mContext = context.getApplicationContext();
LogUtils.initLogging(mContext);
DefaultDialerManagerAdapter defaultDialerAdapter =
@@ -255,7 +255,8 @@ public class TelecomSystem {
asyncRingtonePlayer,
phoneNumberUtilsAdapter,
emergencyCallHelper,
- toneGeneratorFactory);
+ toneGeneratorFactory,
+ clockProxy);
mIncomingCallNotifier = incomingCallNotifier;
incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
diff --git a/src/com/android/server/telecom/components/TelecomService.java b/src/com/android/server/telecom/components/TelecomService.java
index d9d60b86..19dd404e 100644
--- a/src/com/android/server/telecom/components/TelecomService.java
+++ b/src/com/android/server/telecom/components/TelecomService.java
@@ -25,6 +25,7 @@ import android.media.ToneGenerator;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.telecom.Log;
import com.android.internal.telephony.CallerInfoAsyncQuery;
@@ -33,6 +34,7 @@ import com.android.server.telecom.BluetoothAdapterProxy;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallsManager;
+import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.HeadsetMediaButton;
import com.android.server.telecom.HeadsetMediaButtonFactory;
@@ -161,8 +163,18 @@ public class TelecomService extends Service implements TelecomSystem.Component {
new AsyncRingtonePlayer(),
new PhoneNumberUtilsAdapterImpl(),
new IncomingCallNotifier(context),
- ToneGenerator::new
- ));
+ ToneGenerator::new,
+ new ClockProxy() {
+ @Override
+ public long currentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ @Override
+ public long elapsedRealtime() {
+ return SystemClock.elapsedRealtime();
+ }
+ }));
}
if (BluetoothAdapter.getDefaultAdapter() != null) {
context.startService(new Intent(context, BluetoothPhoneService.class));
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index ce774a78..905a15e6 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -82,11 +82,22 @@ public class BasicCallTests extends TelecomSystemTest {
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ assertEquals(TEST_CONNECT_TIME,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getConnectTimeMillis());
+ assertEquals(TEST_CONNECT_TIME,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getConnectTimeMillis());
+ assertEquals(TEST_CREATE_TIME,
+ mInCallServiceFixtureX.getCall(ids.mCallId).getCreationTimeMillis());
+ assertEquals(TEST_CREATE_TIME,
+ mInCallServiceFixtureY.getCall(ids.mCallId).getCreationTimeMillis());
+
verifyNoBlockChecks();
}
@@ -95,6 +106,8 @@ public class BasicCallTests extends TelecomSystemTest {
IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -219,6 +232,8 @@ public class BasicCallTests extends TelecomSystemTest {
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -231,6 +246,8 @@ public class BasicCallTests extends TelecomSystemTest {
IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -290,6 +307,8 @@ public class BasicCallTests extends TelecomSystemTest {
IdPair ids = outgoingCallPhoneAccountSelected(mPhoneAccountA0.getAccountHandle(),
startingNumConnections, startingNumCalls, mConnectionServiceFixtureA);
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(ids.mConnectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED,
mInCallServiceFixtureX.getCall(ids.mCallId).getState());
@@ -341,6 +360,8 @@ public class BasicCallTests extends TelecomSystemTest {
@LargeTest
public void testIncomingCallCallerInfoLookupTimesOutIsAllowed() throws Exception {
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
Bundle extras = new Bundle();
extras.putParcelable(
TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
@@ -377,6 +398,8 @@ public class BasicCallTests extends TelecomSystemTest {
verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
.addCall(any(ParcelableCall.class));
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
disconnectCall(mInCallServiceFixtureX.mLatestCallId,
mConnectionServiceFixtureA.mLatestConnectionId);
}
@@ -736,9 +759,15 @@ public class BasicCallTests extends TelecomSystemTest {
}
private void disconnectCall(String callId, String connectionId) throws Exception {
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_DISCONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_DISCONNECT_ELAPSED_TIME);
mConnectionServiceFixtureA.sendSetDisconnected(connectionId, DisconnectCause.LOCAL);
assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureX.getCall(callId).getState());
assertEquals(Call.STATE_DISCONNECTED, mInCallServiceFixtureY.getCall(callId).getState());
+ assertEquals(TEST_CREATE_TIME,
+ mInCallServiceFixtureX.getCall(callId).getCreationTimeMillis());
+ assertEquals(TEST_CREATE_TIME,
+ mInCallServiceFixtureY.getCall(callId).getCreationTimeMillis());
}
/**
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index e815b5cb..39f70c8c 100644
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -50,7 +50,6 @@ import com.google.android.collect.Lists;
import java.lang.Override;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -410,6 +409,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
IVideoProvider videoProvider;
int videoState;
long connectTimeMillis;
+ long connectElapsedTimeMillis;
StatusHints statusHints;
Bundle extras;
}
@@ -640,6 +640,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
c.videoProvider,
c.videoState,
c.connectTimeMillis,
+ c.connectElapsedTimeMillis,
c.statusHints,
c.extras);
}
@@ -660,6 +661,7 @@ public class ConnectionServiceFixture implements TestFixture<IConnectionService>
false, /* ringback requested */
false, /* voip audio mode */
0, /* Connect Time for conf call on this connection */
+ 0, /* Connect Real Time comes from conference call */
c.statusHints,
c.disconnectCause,
c.conferenceableConnectionIds,
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 205d7788..e51a9c75 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -65,11 +65,10 @@ import com.android.internal.telecom.IInCallAdapter;
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.BluetoothPhoneServiceImpl;
import com.android.server.telecom.CallAudioManager;
-import com.android.server.telecom.CallAudioRouteStateMachine;
-import com.android.server.telecom.CallerInfoAsyncQueryFactory;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.CallsManagerListenerBase;
+import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.HeadsetMediaButton;
import com.android.server.telecom.HeadsetMediaButtonFactory;
@@ -83,7 +82,6 @@ import com.android.server.telecom.ProximitySensorManager;
import com.android.server.telecom.ProximitySensorManagerFactory;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;
-import com.android.server.telecom.callfiltering.AsyncBlockCheckFilter;
import com.android.server.telecom.components.UserCallIntentProcessor;
import com.android.server.telecom.ui.IncomingCallNotifier;
import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
@@ -108,6 +106,16 @@ public class TelecomSystemTest extends TelecomTestCase {
static final int TEST_POLL_INTERVAL = 10; // milliseconds
static final int TEST_TIMEOUT = 1000; // milliseconds
+ // Purposely keep the connect time (which is wall clock) and elapsed time (which is time since
+ // boot) different to test that wall clock time operations and elapsed time operations perform
+ // as they individually should.
+ static final long TEST_CREATE_TIME = 100;
+ static final long TEST_CREATE_ELAPSED_TIME = 200;
+ static final long TEST_CONNECT_TIME = 1000;
+ static final long TEST_CONNECT_ELAPSED_TIME = 2000;
+ static final long TEST_DISCONNECT_TIME = 8000;
+ static final long TEST_DISCONNECT_ELAPSED_TIME = 4000;
+
public class HeadsetMediaButtonFactoryF implements HeadsetMediaButtonFactory {
@Override
public HeadsetMediaButton create(Context context, CallsManager callsManager,
@@ -194,6 +202,7 @@ public class TelecomSystemTest extends TelecomTestCase {
@Mock BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
@Mock AsyncRingtonePlayer mAsyncRingtonePlayer;
@Mock IncomingCallNotifier mIncomingCallNotifier;
+ @Mock ClockProxy mClockProxy;
final ComponentName mInCallServiceComponentNameX =
new ComponentName(
@@ -393,7 +402,9 @@ public class TelecomSystemTest extends TelecomTestCase {
when(mTimeoutsAdapter.getCallScreeningTimeoutMillis(any(ContentResolver.class)))
.thenReturn(TEST_TIMEOUT / 5L);
mIncomingCallNotifier = mock(IncomingCallNotifier.class);
-
+ mClockProxy = mock(ClockProxy.class);
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CREATE_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CREATE_ELAPSED_TIME);
mTelecomSystem = new TelecomSystem(
mComponentContextFixture.getTestDouble(),
new MissedCallNotifierImplFactory() {
@@ -426,7 +437,8 @@ public class TelecomSystemTest extends TelecomTestCase {
mAsyncRingtonePlayer,
mPhoneNumberUtilsAdapter,
mIncomingCallNotifier,
- (streamType, volume) -> mock(ToneGenerator.class));
+ (streamType, volume) -> mock(ToneGenerator.class),
+ mClockProxy);
mComponentContextFixture.setTelecomManager(new TelecomManager(
mComponentContextFixture.getTestDouble(),
@@ -891,6 +903,8 @@ public class TelecomSystemTest extends TelecomTestCase {
connectionServiceFixture.sendSetVideoState(ids.mConnectionId);
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
connectionServiceFixture.sendSetActive(ids.mConnectionId);
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
@@ -928,6 +942,8 @@ public class TelecomSystemTest extends TelecomTestCase {
.answerVideo(eq(ids.mConnectionId), eq(videoState), any());
}
+ when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
+ when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
connectionServiceFixture.sendSetActive(ids.mConnectionId);
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());