diff options
8 files changed, 192 insertions, 50 deletions
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/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()); |