Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbff38cd authored by Brad Ebinger's avatar Brad Ebinger Committed by android-build-merger
Browse files

Merge "Support Emergency calling in CTS"

am: 80f9553c

Change-Id: I121d409e5d9d21f998d07c5cecb907ac1d17e4fd
parents 8a3b8221 80f9553c
Loading
Loading
Loading
Loading
+34 −2
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
import android.text.TextUtils;
import android.util.StatsLog;
import android.os.UserHandle;
@@ -62,11 +64,13 @@ import java.io.IOException;
import java.lang.String;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -336,6 +340,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,

    private boolean mIsEmergencyCall;

    // The Call is considered an emergency call for testing, but will not actually connect to
    // emergency services.
    private boolean mIsTestEmergencyCall;

    private boolean mSpeakerphoneOn;

    private boolean mIsDisconnectingChildCall = false;
@@ -1072,10 +1080,13 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
            // call, it will remain so for the rest of it's lifetime.
            if (!mIsEmergencyCall) {
                mIsEmergencyCall = mHandle != null &&
                        mPhoneNumberUtilsAdapter.isLocalEmergencyNumber(mContext,
                                mHandle.getSchemeSpecificPart());
                        getTelephonyManager().isEmergencyNumber(mHandle.getSchemeSpecificPart());
                mAnalytics.setCallIsEmergency(mIsEmergencyCall);
            }
            if (!mIsTestEmergencyCall) {
                mIsTestEmergencyCall = mHandle != null &&
                        isTestEmergencyCall(mHandle.getSchemeSpecificPart());
            }
            startCallerInfoLookup();
            for (Listener l : mListeners) {
                l.onHandleChanged(this);
@@ -1083,6 +1094,14 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    private boolean isTestEmergencyCall(String number) {
        Map<Integer, List<EmergencyNumber>> eMap = getTelephonyManager().getEmergencyNumberList();
        return eMap.values().stream().flatMap(Collection::stream)
                .anyMatch(eNumber ->
                        eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST) &&
                                number.equals(eNumber.getNumber()));
    }

    public String getCallerDisplayName() {
        return mCallerDisplayName;
    }
@@ -1142,6 +1161,15 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        return mIsEmergencyCall;
    }

    /**
     * @return {@code true} if this an outgoing call to a test emergency number (and NOT to
     * emergency services). Used for testing purposes to differentiate between a real and fake
     * emergency call for safety reasons during testing.
     */
    public boolean isTestEmergencyCall() {
        return mIsTestEmergencyCall;
    }

    /**
     * @return {@code true} if the network has identified this call as an emergency call.
     */
@@ -3161,6 +3189,10 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        }
    }

    private TelephonyManager getTelephonyManager() {
        return mContext.getSystemService(TelephonyManager.class);
    }

    /**
     * Sets whether this {@link Call} is a conference or not.
     * @param isConference
+21 −14
Original line number Diff line number Diff line
@@ -38,11 +38,16 @@ public class CallIntentProcessor {
    }

    public static class AdapterImpl implements Adapter {
        private final DefaultDialerCache mDefaultDialerCache;
        public AdapterImpl(DefaultDialerCache cache) {
            mDefaultDialerCache = cache;
        }

        @Override
        public void processOutgoingCallIntent(Context context, CallsManager callsManager,
                Intent intent, String callingPackage) {
            CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent,
                    callingPackage);
                    callingPackage, mDefaultDialerCache);
        }

        @Override
@@ -58,11 +63,6 @@ public class CallIntentProcessor {

    public static final String KEY_IS_UNKNOWN_CALL = "is_unknown_call";
    public static final String KEY_IS_INCOMING_CALL = "is_incoming_call";
    /*
     *  Whether or not the dialer initiating this outgoing call is the default dialer, or system
     *  dialer and thus allowed to make emergency calls.
     */
    public static final String KEY_IS_PRIVILEGED_DIALER = "is_privileged_dialer";

    /**
     * The user initiating the outgoing call.
@@ -72,10 +72,13 @@ public class CallIntentProcessor {

    private final Context mContext;
    private final CallsManager mCallsManager;
    private final DefaultDialerCache mDefaultDialerCache;

    public CallIntentProcessor(Context context, CallsManager callsManager) {
    public CallIntentProcessor(Context context, CallsManager callsManager,
            DefaultDialerCache defaultDialerCache) {
        this.mContext = context;
        this.mCallsManager = callsManager;
        this.mDefaultDialerCache = defaultDialerCache;
    }

    public void processIntent(Intent intent, String callingPackage) {
@@ -86,7 +89,8 @@ public class CallIntentProcessor {
        if (isUnknownCall) {
            processUnknownCallIntent(mCallsManager, intent);
        } else {
            processOutgoingCallIntent(mContext, mCallsManager, intent, callingPackage);
            processOutgoingCallIntent(mContext, mCallsManager, intent, callingPackage,
                    mDefaultDialerCache);
        }
        Trace.endSection();
    }
@@ -102,7 +106,8 @@ public class CallIntentProcessor {
            Context context,
            CallsManager callsManager,
            Intent intent,
            String callingPackage) {
            String callingPackage,
            DefaultDialerCache defaultDialerCache) {

        Uri handle = intent.getData();
        String scheme = handle.getScheme();
@@ -157,6 +162,9 @@ public class CallIntentProcessor {

        UserHandle initiatingUser = intent.getParcelableExtra(KEY_INITIATING_USER);

        boolean isPrivilegedDialer = defaultDialerCache.isDefaultOrSystemDialer(callingPackage,
                initiatingUser.getIdentifier());

        // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
        CompletableFuture<Call> callFuture = callsManager
                .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
@@ -167,7 +175,8 @@ public class CallIntentProcessor {
            if (call != null) {
                Log.continueSession(logSubsession, "CIP.sNOCI");
                try {
                    sendNewOutgoingCallIntent(context, call, callsManager, intent);
                    sendNewOutgoingCallIntent(context, call, callsManager, intent,
                            isPrivilegedDialer, defaultDialerCache);
                } finally {
                    Log.endSession();
                }
@@ -176,17 +185,15 @@ public class CallIntentProcessor {
    }

    static void sendNewOutgoingCallIntent(Context context, Call call, CallsManager callsManager,
            Intent intent) {
            Intent intent, boolean isPrivilegedDialer, DefaultDialerCache defaultDialerCache) {
        // Asynchronous calls should not usually be made inside a BroadcastReceiver because once
        // onReceive is complete, the BroadcastReceiver's process runs the risk of getting
        // killed if memory is scarce. However, this is OK here because the entire Telecom
        // process will be running throughout the duration of the phone call and should never
        // be killed.
        final boolean isPrivilegedDialer = intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER, false);

        NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                context, callsManager, call, intent, callsManager.getPhoneNumberUtilsAdapter(),
                isPrivilegedDialer);
                isPrivilegedDialer, defaultDialerCache);

        // If the broadcaster comes back with an immediate error, disconnect and show a dialog.
        NewOutgoingCallIntentBroadcaster.CallDisposition disposition = broadcaster.evaluateCall();
+7 −4
Original line number Diff line number Diff line
@@ -1627,6 +1627,7 @@ public class CallsManager extends Call.ListenerBase
     * @param handle The handle of the outgoing call; used to determine the SIP scheme when matching
     *               phone accounts.
     * @param isVideo {@code true} if the call is a video call, {@code false} otherwise.
     * @param isEmergency {@code true} if the call is an emergency call.
     * @param initiatingUser The {@link UserHandle} the call is placed on.
     * @return
     */
@@ -1757,7 +1758,7 @@ public class CallsManager extends Call.ListenerBase
            Log.w(this, "onCallRedirectionComplete: phoneAccountHandle is null");
            endEarly = true;
            disconnectReason = "Null phoneAccountHandle from Call Redirection Service";
        } else if (mPhoneNumberUtilsAdapter.isPotentialLocalEmergencyNumber(mContext,
        } else if (getTelephonyManager().isPotentialEmergencyNumber(
                handle.getSchemeSpecificPart())) {
            Log.w(this, "onCallRedirectionComplete: emergency number %s is redirected from Call"
                    + " Redirection Service", handle.getSchemeSpecificPart());
@@ -2229,10 +2230,8 @@ public class CallsManager extends Call.ListenerBase
                        isEmergency ? 0 : PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY);
        // First check the Radio SIM Technology
        if(mRadioSimVariants == null) {
            TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
                    Context.TELEPHONY_SERVICE);
            // Cache Sim Variants
            mRadioSimVariants = tm.getMultiSimConfiguration();
            mRadioSimVariants = getTelephonyManager().getMultiSimConfiguration();
        }
        // Only one SIM PhoneAccount can be active at one time for DSDS. Only that SIM PhoneAccount
        // Should be available if a call is already active on the SIM account.
@@ -2256,6 +2255,10 @@ public class CallsManager extends Call.ListenerBase
        return allAccounts;
    }

    private TelephonyManager getTelephonyManager() {
        return mContext.getSystemService(TelephonyManager.class);
    }

    /**
     * Informs listeners (notably {@link CallAudioManager} of a change to the call's external
     * property.
+6 −0
Original line number Diff line number Diff line
@@ -383,6 +383,12 @@ public class CreateConnectionProcessor implements CreateConnectionResponse {
                allAccounts.add(TelephonyUtil.getDefaultEmergencyPhoneAccount());
            }

            // When testing emergency calls, we want the calls to go through to the test connection
            // service, not the telephony ConnectionService.
            if (mCall.isTestEmergencyCall()) {
                allAccounts = mPhoneAccountRegistrar.filterRestrictedPhoneAccounts(allAccounts);
            }

            // Get user preferred PA if it exists.
            PhoneAccount preferredPA = mPhoneAccountRegistrar.getPhoneAccountUnchecked(
                    preferredPAH);
+26 −3
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.server.telecom;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
@@ -134,9 +136,10 @@ public class DefaultDialerCache {
    private final Context mContext;
    private final DefaultDialerManagerAdapter mDefaultDialerManagerAdapter;
    private final TelecomSystem.SyncRoot mLock;
    private final String mSystemDialerName;
    private final ComponentName mSystemDialerComponentName;
    private final RoleManagerAdapter mRoleManagerAdapter;
    private SparseArray<String> mCurrentDefaultDialerPerUser = new SparseArray<>();
    private ComponentName mOverrideSystemDialerComponentName;

    public DefaultDialerCache(Context context,
            DefaultDialerManagerAdapter defaultDialerManagerAdapter,
@@ -146,7 +149,11 @@ public class DefaultDialerCache {
        mDefaultDialerManagerAdapter = defaultDialerManagerAdapter;
        mRoleManagerAdapter = roleManagerAdapter;
        mLock = lock;
        mSystemDialerName = TelecomServiceImpl.getSystemDialerPackage(mContext);
        Resources resources = mContext.getResources();
        mSystemDialerComponentName = new ComponentName(resources.getString(
                com.android.internal.R.string.config_defaultDialer),
                resources.getString(R.string.incall_default_class));


        IntentFilter packageIntentFilter = new IntentFilter();
        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -194,6 +201,22 @@ public class DefaultDialerCache {
        return getDefaultDialerApplication(mContext.getUserId());
    }

    public void setSystemDialerComponentName(ComponentName testComponentName) {
        mOverrideSystemDialerComponentName = testComponentName;
    }

    public String getSystemDialerApplication() {
        if (mOverrideSystemDialerComponentName != null) {
            return mOverrideSystemDialerComponentName.getPackageName();
        }
        return mSystemDialerComponentName.getPackageName();
    }

    public ComponentName getSystemDialerComponent() {
        if (mOverrideSystemDialerComponentName != null) return mOverrideSystemDialerComponentName;
        return mSystemDialerComponentName;
    }

    public void observeDefaultDialerApplication(Executor executor, IntConsumer observer) {
        mRoleManagerAdapter.observeDefaultDialerApp(executor, observer);
    }
@@ -201,7 +224,7 @@ public class DefaultDialerCache {
    public boolean isDefaultOrSystemDialer(String packageName, int userId) {
        String defaultDialer = getDefaultDialerApplication(userId);
        return Objects.equals(packageName, defaultDialer)
                || Objects.equals(packageName, mSystemDialerName);
                || Objects.equals(packageName, getSystemDialerApplication());
    }

    public boolean setDefaultDialer(String packageName, int userId) {
Loading