Merge "Set audio mode back to normal before we abandon the audio focus after call." into main
diff --git a/flags/telecom_incallservice_flags.aconfig b/flags/telecom_incallservice_flags.aconfig
index d70b9cc..e1a652b 100644
--- a/flags/telecom_incallservice_flags.aconfig
+++ b/flags/telecom_incallservice_flags.aconfig
@@ -5,4 +5,11 @@
   namespace: "telecom"
   description: "Binds to InCallServices when call requires no call filtering on watch"
   bug: "282113261"
+}
+
+flag {
+  name: "ecc_keyguard"
+  namespace: "telecom"
+  description: "Ensure that users are able to return to call from keyguard UI for ECC"
+  bug: "306582821"
 }
\ No newline at end of file
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index ca264c1..184eadd 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -22,7 +22,9 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.AppOpsManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.content.AttributionSource;
@@ -47,7 +49,6 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.permission.PermissionManager;
 import android.telecom.CallAudioState;
 import android.telecom.CallEndpoint;
 import android.telecom.ConnectionService;
@@ -66,6 +67,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.telecom.SystemStateHelper.SystemStateListener;
+import com.android.server.telecom.flags.FeatureFlags;
 import com.android.server.telecom.ui.NotificationChannelManager;
 
 import java.util.ArrayList;
@@ -1237,11 +1239,12 @@
 
     private ArraySet<String> mAllCarrierPrivilegedApps = new ArraySet<>();
     private ArraySet<String> mActiveCarrierPrivilegedApps = new ArraySet<>();
+    private FeatureFlags mFeatureFlags;
 
     public InCallController(Context context, TelecomSystem.SyncRoot lock, CallsManager callsManager,
             SystemStateHelper systemStateHelper, DefaultDialerCache defaultDialerCache,
             Timeouts.Adapter timeoutsAdapter, EmergencyCallHelper emergencyCallHelper,
-            CarModeTracker carModeTracker, ClockProxy clockProxy) {
+            CarModeTracker carModeTracker, ClockProxy clockProxy, FeatureFlags featureFlags) {
         mContext = context;
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
         mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
@@ -1258,6 +1261,7 @@
         IntentFilter userAddedFilter = new IntentFilter(Intent.ACTION_USER_ADDED);
         userAddedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiver(mUserAddedReceiver, userAddedFilter);
+        mFeatureFlags = featureFlags;
     }
 
     private void restrictPhoneCallOps() {
@@ -1690,6 +1694,29 @@
 
     @VisibleForTesting
     public void bringToForeground(boolean showDialpad, UserHandle callingUser) {
+        KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);
+        boolean isLockscreenRestricted = keyguardManager != null
+                && keyguardManager.isKeyguardLocked();
+        UserHandle currentUser = mCallsManager.getCurrentUserHandle();
+        // Handle cases when calls are placed from the keyguard UI screen, which operates under
+        // the admin user. This needs to account for emergency calls placed from secondary/guest
+        // users as well as the work profile. Once the screen is locked, the user should be able to
+        // return to the call (from the keyguard UI).
+        if (mFeatureFlags.eccKeyguard() && mCallsManager.isInEmergencyCall()
+                && isLockscreenRestricted && !mInCallServices.containsKey(callingUser)) {
+            // If screen is locked and the current user is the system, query calls for the work
+            // profile user, if available. Otherwise, the user is in the secondary/guest profile,
+            // so we can default to the system user.
+            if (currentUser.isSystem()) {
+                UserManager um = mContext.getSystemService(UserManager.class);
+                UserHandle workProfileUser = findChildManagedProfileUser(currentUser, um);
+                boolean hasWorkCalls = mCallsManager.getCalls().stream()
+                        .filter((c) -> getUserFromCall(c).equals(workProfileUser)).count() > 0;
+                callingUser = hasWorkCalls ? workProfileUser : currentUser;
+            } else {
+                callingUser = currentUser;
+            }
+        }
         if (mInCallServices.containsKey(callingUser)) {
             for (IInCallService inCallService : mInCallServices.get(callingUser).values()) {
                 try {
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 63edf9c..379487d 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -294,7 +294,7 @@
                         EmergencyCallHelper emergencyCallHelper) {
                     return new InCallController(context, lock, callsManager, systemStateProvider,
                             defaultDialerCache, timeoutsAdapter, emergencyCallHelper,
-                            new CarModeTracker(), clockProxy);
+                            new CarModeTracker(), clockProxy, featureFlags);
                 }
             };
 
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index 683a5e2..1b5677e 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -28,7 +28,6 @@
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyObject;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -36,7 +35,6 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -236,7 +234,7 @@
                 "com.android.server.telecom.tests", null));
         mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
                 mMockSystemStateHelper, mDefaultDialerCache, mTimeoutsAdapter,
-                mEmergencyCallHelper, mCarModeTracker, mClockProxy);
+                mEmergencyCallHelper, mCarModeTracker, mClockProxy, mFeatureFlags);
         // Capture the broadcast receiver registered.
         doAnswer(invocation -> {
             mRegisteredReceiver = invocation.getArgument(0);