Loading src/com/android/server/telecom/Call.java +29 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; import java.io.IOException; Loading Loading @@ -506,6 +508,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, private final String mId; private String mConnectionId; private Analytics.CallInfo mAnalytics = new Analytics.CallInfo(); private CallStateChangedAtomWriter mCallStateChangedAtomWriter = new CallStateChangedAtomWriter(); private char mPlayingDtmfTone; private boolean mWasConferencePreviouslyMerged = false; Loading Loading @@ -799,6 +803,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mCreationTimeMillis = mClockProxy.currentTimeMillis(); mMissedReason = MISSED_REASON_NOT_MISSED; mStartRingTime = 0; mCallStateChangedAtomWriter.setExistingCallCount(callsManager.getCalls().size()); } /** Loading Loading @@ -1275,10 +1281,15 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } Log.addEvent(this, event, stringData); } int statsdDisconnectCause = (newState == CallState.DISCONNECTED) ? getDisconnectCause().getCode() : DisconnectCause.UNKNOWN; TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, newState, statsdDisconnectCause, isSelfManaged(), isExternalCall(), isEmergencyCall()); mCallStateChangedAtomWriter .setDisconnectCause(getDisconnectCause()) .setSelfManaged(isSelfManaged()) .setExternalCall(isExternalCall()) .setEmergencyCall(isEmergencyCall()) .setDurationSeconds(Long.valueOf( (mDisconnectTimeMillis - mConnectTimeMillis) / 1000).intValue()) .write(newState); } return true; } Loading Loading @@ -1650,6 +1661,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } checkIfVideoCapable(); checkIfRttCapable(); if (accountHandle != null) { mCallStateChangedAtomWriter.setUid( accountHandle.getComponentName().getPackageName(), mContext.getPackageManager()); } } public UserHandle getUserHandleFromTargetPhoneAccount() { Loading Loading @@ -4358,6 +4375,14 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mCallScreeningComponentName = callScreeningComponentName; } public void setStartFailCause(CallFailureCause cause) { mCallStateChangedAtomWriter.setStartFailCause(cause); } public void increaseHeldByThisCallCount() { mCallStateChangedAtomWriter.increaseHeldCallCount(); } public void maybeOnInCallServiceTrackingChanged(boolean isTracking, boolean hasUi) { if (mTransactionalService != null) { Log.i(this, Loading src/com/android/server/telecom/CallAnomalyWatchdog.java +7 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.util.LocalLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import java.util.Collections; import java.util.Map; Loading Loading @@ -345,9 +346,12 @@ public class CallAnomalyWatchdog extends CallsManagerListenerBase implements Cal } private void writeCallStateChangedAtom(Call call) { TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, call.getState(), DisconnectCause.ERROR, call.isSelfManaged(), call.isExternalCall(), call.isEmergencyCall()); new CallStateChangedAtomWriter() .setDisconnectCause(call.getDisconnectCause()) .setSelfManaged(call.isSelfManaged()) .setExternalCall(call.isExternalCall()) .setEmergencyCall(call.isEmergencyCall()) .write(call.getState()); } /** Loading src/com/android/server/telecom/CallsManager.java +42 −10 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.components.ErrorDialogActivity; import com.android.server.telecom.components.TelecomBroadcastReceiver; import com.android.server.telecom.settings.BlockedNumbersUtil; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.ui.AudioProcessingNotification; import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity; import com.android.server.telecom.ui.ConfirmCallDialogActivity; Loading Loading @@ -1496,16 +1497,20 @@ public class CallsManager extends Call.ListenerBase } } if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call, call.getTargetPhoneAccount()))) { CallFailureCause startFailCause = checkIncomingCallPermitted(call, call.getTargetPhoneAccount()); if (!isHandoverAllowed || (call.isSelfManaged() && !startFailCause.isSuccess())) { if (isConference) { notifyCreateConferenceFailed(phoneAccountHandle, call); } else { if (hasMaximumManagedRingingCalls(call)) { call.setMissedReason(AUTO_MISSED_MAXIMUM_RINGING); call.setStartFailCause(CallFailureCause.MAX_RINGING_CALLS); mCallLogManager.logCall(call, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/, null /*CallFilteringResult*/); } call.setStartFailCause(startFailCause); notifyCreateConnectionFailed(phoneAccountHandle, call); } } else if (isInEmergencyCall()) { Loading @@ -1514,6 +1519,7 @@ public class CallsManager extends Call.ListenerBase // rejected since the user did not explicitly reject. call.setMissedReason(AUTO_MISSED_EMERGENCY_CALL); call.getAnalytics().setMissedReason(call.getMissedReason()); call.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); mCallLogManager.logCall(call, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/, null /*CallFilteringResult*/); if (isConference) { Loading Loading @@ -1829,6 +1835,7 @@ public class CallsManager extends Call.ListenerBase notifyCreateConnectionFailed( finalCall.getTargetPhoneAccount(), finalCall); } finalCall.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); return CompletableFuture.completedFuture(null); } Loading Loading @@ -3292,6 +3299,7 @@ public class CallsManager extends Call.ListenerBase Log.i(this, "holdActiveCallForNewCall: Holding active %s before making %s active.", activeCall.getId(), call.getId()); activeCall.hold(); call.increaseHeldByThisCallCount(); return true; } else { // This call does not support hold. If it is from a different connection Loading Loading @@ -4534,6 +4542,7 @@ public class CallsManager extends Call.ListenerBase } // If the user tries to make two outgoing calls to different emergency call numbers, // we will try to connect the first outgoing call and reject the second. emergencyCall.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); return false; } Loading Loading @@ -4621,12 +4630,14 @@ public class CallsManager extends Call.ListenerBase if (canHold(liveCall)) { Log.i(this, "makeRoomForOutgoingEmergencyCall: holding live call."); emergencyCall.getAnalytics().setCallIsAdditional(true); emergencyCall.increaseHeldByThisCallCount(); liveCall.getAnalytics().setCallIsInterrupted(true); liveCall.hold("calling " + emergencyCall.getId()); return true; } // The live call cannot be held so we're out of luck here. There's no room. emergencyCall.setStartFailCause(CallFailureCause.CANNOT_HOLD_CALL); return false; } Loading Loading @@ -4668,6 +4679,7 @@ public class CallsManager extends Call.ListenerBase + " of new outgoing call."); return true; } call.setStartFailCause(CallFailureCause.MAX_OUTGOING_CALLS); return false; } Loading Loading @@ -4716,6 +4728,7 @@ public class CallsManager extends Call.ListenerBase } // The live call cannot be held so we're out of luck here. There's no room. call.setStartFailCause(CallFailureCause.CANNOT_HOLD_CALL); return false; } Loading Loading @@ -4940,25 +4953,44 @@ public class CallsManager extends Call.ListenerBase public boolean isIncomingCallPermitted(Call excludeCall, PhoneAccountHandle phoneAccountHandle) { return checkIncomingCallPermitted(excludeCall, phoneAccountHandle).isSuccess(); } private CallFailureCause checkIncomingCallPermitted( Call call, PhoneAccountHandle phoneAccountHandle) { if (phoneAccountHandle == null) { return false; return CallFailureCause.INVALID_USE; } PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); if (phoneAccount == null) { return false; return CallFailureCause.INVALID_USE; } if (isInEmergencyCall()) return false; if (!phoneAccount.isSelfManaged()) { return !hasMaximumManagedRingingCalls(excludeCall) && !hasMaximumManagedHoldingCalls(excludeCall); if (isInEmergencyCall()) { return CallFailureCause.IN_EMERGENCY_CALL; } if (phoneAccount.isSelfManaged()) { if (hasMaximumSelfManagedRingingCalls(call, phoneAccountHandle)) { return CallFailureCause.MAX_RINGING_CALLS; } if (hasMaximumSelfManagedCalls(call, phoneAccountHandle)) { return CallFailureCause.MAX_SELF_MANAGED_CALLS; } } else { return !hasMaximumSelfManagedRingingCalls(excludeCall, phoneAccountHandle) && !hasMaximumSelfManagedCalls(excludeCall, phoneAccountHandle); if (hasMaximumManagedRingingCalls(call)) { return CallFailureCause.MAX_RINGING_CALLS; } if (hasMaximumManagedHoldingCalls(call)) { return CallFailureCause.MAX_HOLD_CALLS; } } return CallFailureCause.NONE; } public boolean isOutgoingCallPermitted(PhoneAccountHandle phoneAccountHandle) { return isOutgoingCallPermitted(null /* excludeCall */, phoneAccountHandle); } Loading src/com/android/server/telecom/stats/CallFailureCause.java 0 → 100644 +69 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.stats; /** * Indicating the failure reason why a new call cannot be made. * The codes are synced with CallFailureCauseEnum defined in enums.proto. */ public enum CallFailureCause { /** The call is normally started. */ NONE(0), /** Necessary parameters are invalid or null. */ INVALID_USE(1), /** There is an emergency call ongoing. */ IN_EMERGENCY_CALL(2), /** There is an live call that cannot be held. */ CANNOT_HOLD_CALL(3), /** There are maximum number of outgoing calls already. */ MAX_OUTGOING_CALLS(4), /** There are maximum number of ringing calls already. */ MAX_RINGING_CALLS(5), /** There are maximum number of calls in hold already. */ MAX_HOLD_CALLS(6), /* There are maximum number of self-managed calls already. */ MAX_SELF_MANAGED_CALLS(7); private final int mCode; /** * Creates a new CallFailureCause. * * @param code The code for the failure cause. */ CallFailureCause(int code) { mCode = code; } /** * Returns the code for the failure. * * @return The code for the failure cause. */ public int getCode() { return mCode; } /** * Check if this enum represents a non-failure case. * * @return True if success. */ public boolean isSuccess() { return this == NONE; } } src/com/android/server/telecom/stats/CallStateChangedAtomWriter.java 0 → 100644 +119 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.stats; import android.content.pm.PackageManager; import android.telecom.DisconnectCause; import android.telecom.Log; import com.android.server.telecom.CallState; import com.android.server.telecom.TelecomStatsLog; /** * Collects and stores data for CallStateChanged atom for each call, and provide a * method to write the data to statsd whenever the call state changes. */ public class CallStateChangedAtomWriter { private boolean mIsSelfManaged = false; private boolean mIsExternalCall = false; private boolean mIsEmergencyCall = false; private int mUid = -1; private int mDurationSeconds = 0; private int mExistingCallCount = 0; private int mHeldCallCount = 0; private CallFailureCause mStartFailCause = CallFailureCause.NONE; private DisconnectCause mDisconnectCause = new DisconnectCause(DisconnectCause.UNKNOWN); /** * Write collected data and current call state to statsd. * * @param state Current call state. */ public void write(int state) { TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, state, state == CallState.DISCONNECTED ? mDisconnectCause.getCode() : DisconnectCause.UNKNOWN, mIsSelfManaged, mIsExternalCall, mIsEmergencyCall, mUid, state == CallState.DISCONNECTED ? mDurationSeconds : 0, mExistingCallCount, mHeldCallCount, state == CallState.DISCONNECTED ? mStartFailCause.getCode() : CallFailureCause.NONE.getCode()); } public CallStateChangedAtomWriter setSelfManaged(boolean isSelfManaged) { mIsSelfManaged = isSelfManaged; return this; } public CallStateChangedAtomWriter setExternalCall(boolean isExternalCall) { mIsExternalCall = isExternalCall; return this; } public CallStateChangedAtomWriter setEmergencyCall(boolean isEmergencyCall) { mIsEmergencyCall = isEmergencyCall; return this; } public CallStateChangedAtomWriter setUid(int uid) { mUid = uid; return this; } public CallStateChangedAtomWriter setUid(String packageName, PackageManager pm) { try { final int uid = pm.getPackageUid(packageName, PackageManager.PackageInfoFlags.of(0)); return setUid(uid); } catch (PackageManager.NameNotFoundException e) { Log.e(this, e, "Could not find the package"); } return setUid(-1); } public CallStateChangedAtomWriter setDurationSeconds(int duration) { if (duration >= 0) { mDurationSeconds = duration; } return this; } public CallStateChangedAtomWriter setExistingCallCount(int count) { mExistingCallCount = count; return this; } public CallStateChangedAtomWriter increaseHeldCallCount() { mHeldCallCount++; return this; } public CallStateChangedAtomWriter setDisconnectCause(DisconnectCause cause) { mDisconnectCause = cause; return this; } public CallStateChangedAtomWriter setStartFailCause(CallFailureCause cause) { mStartFailCause = cause; return this; } } Loading
src/com/android/server/telecom/Call.java +29 −4 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ import android.widget.Toast; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telecom.IVideoProvider; import com.android.internal.util.Preconditions; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import com.android.server.telecom.ui.ToastFactory; import java.io.IOException; Loading Loading @@ -506,6 +508,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, private final String mId; private String mConnectionId; private Analytics.CallInfo mAnalytics = new Analytics.CallInfo(); private CallStateChangedAtomWriter mCallStateChangedAtomWriter = new CallStateChangedAtomWriter(); private char mPlayingDtmfTone; private boolean mWasConferencePreviouslyMerged = false; Loading Loading @@ -799,6 +803,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mCreationTimeMillis = mClockProxy.currentTimeMillis(); mMissedReason = MISSED_REASON_NOT_MISSED; mStartRingTime = 0; mCallStateChangedAtomWriter.setExistingCallCount(callsManager.getCalls().size()); } /** Loading Loading @@ -1275,10 +1281,15 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } Log.addEvent(this, event, stringData); } int statsdDisconnectCause = (newState == CallState.DISCONNECTED) ? getDisconnectCause().getCode() : DisconnectCause.UNKNOWN; TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, newState, statsdDisconnectCause, isSelfManaged(), isExternalCall(), isEmergencyCall()); mCallStateChangedAtomWriter .setDisconnectCause(getDisconnectCause()) .setSelfManaged(isSelfManaged()) .setExternalCall(isExternalCall()) .setEmergencyCall(isEmergencyCall()) .setDurationSeconds(Long.valueOf( (mDisconnectTimeMillis - mConnectTimeMillis) / 1000).intValue()) .write(newState); } return true; } Loading Loading @@ -1650,6 +1661,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, } checkIfVideoCapable(); checkIfRttCapable(); if (accountHandle != null) { mCallStateChangedAtomWriter.setUid( accountHandle.getComponentName().getPackageName(), mContext.getPackageManager()); } } public UserHandle getUserHandleFromTargetPhoneAccount() { Loading Loading @@ -4358,6 +4375,14 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable, mCallScreeningComponentName = callScreeningComponentName; } public void setStartFailCause(CallFailureCause cause) { mCallStateChangedAtomWriter.setStartFailCause(cause); } public void increaseHeldByThisCallCount() { mCallStateChangedAtomWriter.increaseHeldCallCount(); } public void maybeOnInCallServiceTrackingChanged(boolean isTracking, boolean hasUi) { if (mTransactionalService != null) { Log.i(this, Loading
src/com/android/server/telecom/CallAnomalyWatchdog.java +7 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.util.LocalLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.telecom.stats.CallStateChangedAtomWriter; import java.util.Collections; import java.util.Map; Loading Loading @@ -345,9 +346,12 @@ public class CallAnomalyWatchdog extends CallsManagerListenerBase implements Cal } private void writeCallStateChangedAtom(Call call) { TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, call.getState(), DisconnectCause.ERROR, call.isSelfManaged(), call.isExternalCall(), call.isEmergencyCall()); new CallStateChangedAtomWriter() .setDisconnectCause(call.getDisconnectCause()) .setSelfManaged(call.isSelfManaged()) .setExternalCall(call.isExternalCall()) .setEmergencyCall(call.isEmergencyCall()) .write(call.getState()); } /** Loading
src/com/android/server/telecom/CallsManager.java +42 −10 Original line number Diff line number Diff line Loading @@ -125,6 +125,7 @@ import com.android.server.telecom.callredirection.CallRedirectionProcessor; import com.android.server.telecom.components.ErrorDialogActivity; import com.android.server.telecom.components.TelecomBroadcastReceiver; import com.android.server.telecom.settings.BlockedNumbersUtil; import com.android.server.telecom.stats.CallFailureCause; import com.android.server.telecom.ui.AudioProcessingNotification; import com.android.server.telecom.ui.CallRedirectionTimeoutDialogActivity; import com.android.server.telecom.ui.ConfirmCallDialogActivity; Loading Loading @@ -1496,16 +1497,20 @@ public class CallsManager extends Call.ListenerBase } } if (!isHandoverAllowed || (call.isSelfManaged() && !isIncomingCallPermitted(call, call.getTargetPhoneAccount()))) { CallFailureCause startFailCause = checkIncomingCallPermitted(call, call.getTargetPhoneAccount()); if (!isHandoverAllowed || (call.isSelfManaged() && !startFailCause.isSuccess())) { if (isConference) { notifyCreateConferenceFailed(phoneAccountHandle, call); } else { if (hasMaximumManagedRingingCalls(call)) { call.setMissedReason(AUTO_MISSED_MAXIMUM_RINGING); call.setStartFailCause(CallFailureCause.MAX_RINGING_CALLS); mCallLogManager.logCall(call, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/, null /*CallFilteringResult*/); } call.setStartFailCause(startFailCause); notifyCreateConnectionFailed(phoneAccountHandle, call); } } else if (isInEmergencyCall()) { Loading @@ -1514,6 +1519,7 @@ public class CallsManager extends Call.ListenerBase // rejected since the user did not explicitly reject. call.setMissedReason(AUTO_MISSED_EMERGENCY_CALL); call.getAnalytics().setMissedReason(call.getMissedReason()); call.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); mCallLogManager.logCall(call, Calls.MISSED_TYPE, true /*showNotificationForMissedCall*/, null /*CallFilteringResult*/); if (isConference) { Loading Loading @@ -1829,6 +1835,7 @@ public class CallsManager extends Call.ListenerBase notifyCreateConnectionFailed( finalCall.getTargetPhoneAccount(), finalCall); } finalCall.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); return CompletableFuture.completedFuture(null); } Loading Loading @@ -3292,6 +3299,7 @@ public class CallsManager extends Call.ListenerBase Log.i(this, "holdActiveCallForNewCall: Holding active %s before making %s active.", activeCall.getId(), call.getId()); activeCall.hold(); call.increaseHeldByThisCallCount(); return true; } else { // This call does not support hold. If it is from a different connection Loading Loading @@ -4534,6 +4542,7 @@ public class CallsManager extends Call.ListenerBase } // If the user tries to make two outgoing calls to different emergency call numbers, // we will try to connect the first outgoing call and reject the second. emergencyCall.setStartFailCause(CallFailureCause.IN_EMERGENCY_CALL); return false; } Loading Loading @@ -4621,12 +4630,14 @@ public class CallsManager extends Call.ListenerBase if (canHold(liveCall)) { Log.i(this, "makeRoomForOutgoingEmergencyCall: holding live call."); emergencyCall.getAnalytics().setCallIsAdditional(true); emergencyCall.increaseHeldByThisCallCount(); liveCall.getAnalytics().setCallIsInterrupted(true); liveCall.hold("calling " + emergencyCall.getId()); return true; } // The live call cannot be held so we're out of luck here. There's no room. emergencyCall.setStartFailCause(CallFailureCause.CANNOT_HOLD_CALL); return false; } Loading Loading @@ -4668,6 +4679,7 @@ public class CallsManager extends Call.ListenerBase + " of new outgoing call."); return true; } call.setStartFailCause(CallFailureCause.MAX_OUTGOING_CALLS); return false; } Loading Loading @@ -4716,6 +4728,7 @@ public class CallsManager extends Call.ListenerBase } // The live call cannot be held so we're out of luck here. There's no room. call.setStartFailCause(CallFailureCause.CANNOT_HOLD_CALL); return false; } Loading Loading @@ -4940,25 +4953,44 @@ public class CallsManager extends Call.ListenerBase public boolean isIncomingCallPermitted(Call excludeCall, PhoneAccountHandle phoneAccountHandle) { return checkIncomingCallPermitted(excludeCall, phoneAccountHandle).isSuccess(); } private CallFailureCause checkIncomingCallPermitted( Call call, PhoneAccountHandle phoneAccountHandle) { if (phoneAccountHandle == null) { return false; return CallFailureCause.INVALID_USE; } PhoneAccount phoneAccount = mPhoneAccountRegistrar.getPhoneAccountUnchecked(phoneAccountHandle); if (phoneAccount == null) { return false; return CallFailureCause.INVALID_USE; } if (isInEmergencyCall()) return false; if (!phoneAccount.isSelfManaged()) { return !hasMaximumManagedRingingCalls(excludeCall) && !hasMaximumManagedHoldingCalls(excludeCall); if (isInEmergencyCall()) { return CallFailureCause.IN_EMERGENCY_CALL; } if (phoneAccount.isSelfManaged()) { if (hasMaximumSelfManagedRingingCalls(call, phoneAccountHandle)) { return CallFailureCause.MAX_RINGING_CALLS; } if (hasMaximumSelfManagedCalls(call, phoneAccountHandle)) { return CallFailureCause.MAX_SELF_MANAGED_CALLS; } } else { return !hasMaximumSelfManagedRingingCalls(excludeCall, phoneAccountHandle) && !hasMaximumSelfManagedCalls(excludeCall, phoneAccountHandle); if (hasMaximumManagedRingingCalls(call)) { return CallFailureCause.MAX_RINGING_CALLS; } if (hasMaximumManagedHoldingCalls(call)) { return CallFailureCause.MAX_HOLD_CALLS; } } return CallFailureCause.NONE; } public boolean isOutgoingCallPermitted(PhoneAccountHandle phoneAccountHandle) { return isOutgoingCallPermitted(null /* excludeCall */, phoneAccountHandle); } Loading
src/com/android/server/telecom/stats/CallFailureCause.java 0 → 100644 +69 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.stats; /** * Indicating the failure reason why a new call cannot be made. * The codes are synced with CallFailureCauseEnum defined in enums.proto. */ public enum CallFailureCause { /** The call is normally started. */ NONE(0), /** Necessary parameters are invalid or null. */ INVALID_USE(1), /** There is an emergency call ongoing. */ IN_EMERGENCY_CALL(2), /** There is an live call that cannot be held. */ CANNOT_HOLD_CALL(3), /** There are maximum number of outgoing calls already. */ MAX_OUTGOING_CALLS(4), /** There are maximum number of ringing calls already. */ MAX_RINGING_CALLS(5), /** There are maximum number of calls in hold already. */ MAX_HOLD_CALLS(6), /* There are maximum number of self-managed calls already. */ MAX_SELF_MANAGED_CALLS(7); private final int mCode; /** * Creates a new CallFailureCause. * * @param code The code for the failure cause. */ CallFailureCause(int code) { mCode = code; } /** * Returns the code for the failure. * * @return The code for the failure cause. */ public int getCode() { return mCode; } /** * Check if this enum represents a non-failure case. * * @return True if success. */ public boolean isSuccess() { return this == NONE; } }
src/com/android/server/telecom/stats/CallStateChangedAtomWriter.java 0 → 100644 +119 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.stats; import android.content.pm.PackageManager; import android.telecom.DisconnectCause; import android.telecom.Log; import com.android.server.telecom.CallState; import com.android.server.telecom.TelecomStatsLog; /** * Collects and stores data for CallStateChanged atom for each call, and provide a * method to write the data to statsd whenever the call state changes. */ public class CallStateChangedAtomWriter { private boolean mIsSelfManaged = false; private boolean mIsExternalCall = false; private boolean mIsEmergencyCall = false; private int mUid = -1; private int mDurationSeconds = 0; private int mExistingCallCount = 0; private int mHeldCallCount = 0; private CallFailureCause mStartFailCause = CallFailureCause.NONE; private DisconnectCause mDisconnectCause = new DisconnectCause(DisconnectCause.UNKNOWN); /** * Write collected data and current call state to statsd. * * @param state Current call state. */ public void write(int state) { TelecomStatsLog.write(TelecomStatsLog.CALL_STATE_CHANGED, state, state == CallState.DISCONNECTED ? mDisconnectCause.getCode() : DisconnectCause.UNKNOWN, mIsSelfManaged, mIsExternalCall, mIsEmergencyCall, mUid, state == CallState.DISCONNECTED ? mDurationSeconds : 0, mExistingCallCount, mHeldCallCount, state == CallState.DISCONNECTED ? mStartFailCause.getCode() : CallFailureCause.NONE.getCode()); } public CallStateChangedAtomWriter setSelfManaged(boolean isSelfManaged) { mIsSelfManaged = isSelfManaged; return this; } public CallStateChangedAtomWriter setExternalCall(boolean isExternalCall) { mIsExternalCall = isExternalCall; return this; } public CallStateChangedAtomWriter setEmergencyCall(boolean isEmergencyCall) { mIsEmergencyCall = isEmergencyCall; return this; } public CallStateChangedAtomWriter setUid(int uid) { mUid = uid; return this; } public CallStateChangedAtomWriter setUid(String packageName, PackageManager pm) { try { final int uid = pm.getPackageUid(packageName, PackageManager.PackageInfoFlags.of(0)); return setUid(uid); } catch (PackageManager.NameNotFoundException e) { Log.e(this, e, "Could not find the package"); } return setUid(-1); } public CallStateChangedAtomWriter setDurationSeconds(int duration) { if (duration >= 0) { mDurationSeconds = duration; } return this; } public CallStateChangedAtomWriter setExistingCallCount(int count) { mExistingCallCount = count; return this; } public CallStateChangedAtomWriter increaseHeldCallCount() { mHeldCallCount++; return this; } public CallStateChangedAtomWriter setDisconnectCause(DisconnectCause cause) { mDisconnectCause = cause; return this; } public CallStateChangedAtomWriter setStartFailCause(CallFailureCause cause) { mStartFailCause = cause; return this; } }