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

Commit 6ac8e711 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Add new system level APIs for accessing IMS state

1) Adds new system APIs that provide more access to IMS state.
2) Remove dependence on IPackageManager, which is not accessible
in mainline.

Bug: 141457496
Bug: 122098288
Test: atest GtsTelephonyTestCases, atest FrameworksTelephonyTests
Change-Id: I17cbad4642ad3099668a354bb2588f2b55602311
parent 8e554f88
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -8304,6 +8304,7 @@ package android.telephony {
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
    method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int);
    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
    method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
@@ -8973,11 +8974,14 @@ package android.telephony.ims {
  public class ImsMmTelManager {
    method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.function.Consumer<java.lang.Boolean>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
@@ -9504,6 +9508,8 @@ package android.telephony.ims.feature {
    method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
    method public void setUiTtyMode(int, @Nullable android.os.Message);
    method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
    field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
    field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
    field public static final int PROCESS_CALL_CSFB = 1; // 0x1
    field public static final int PROCESS_CALL_IMS = 0; // 0x0
  }
+3 −1
Original line number Diff line number Diff line
@@ -9517,10 +9517,12 @@ public class TelephonyManager {
    }

    /**
     * Resets telephony manager settings back to factory defaults.
     * Resets Telephony and IMS settings back to factory defaults.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
    public void factoryReset(int subId) {
        try {
            Log.d(TAG, "factoryReset: subId=" + subId);
+76 −26
Original line number Diff line number Diff line
@@ -25,14 +25,13 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
@@ -42,6 +41,7 @@ import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.ITelephony;

import java.lang.annotation.Retention;
@@ -49,6 +49,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

/**
 * A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated
@@ -64,8 +65,6 @@ import java.util.concurrent.Executor;
@SystemApi
public class ImsMmTelManager {

    private static final String TAG = "ImsMmTelManager";

    /**
     * @hide
     */
@@ -311,7 +310,7 @@ public class ImsMmTelManager {
        }
    }

    private int mSubId;
    private final int mSubId;

    /**
     * Create an instance of {@link ImsMmTelManager} for the subscription id specified.
@@ -366,10 +365,6 @@ public class ImsMmTelManager {
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
        }
        if (!isImsAvailableOnDevice()) {
            throw new ImsException("IMS not available on device.",
                    ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
        }
        c.setExecutor(executor);
        try {
            getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
@@ -378,7 +373,7 @@ public class ImsMmTelManager {
                // Rethrow as runtime error to keep API compatible.
                throw new IllegalArgumentException(e.getMessage());
            } else {
                throw new RuntimeException(e.getMessage());
                throw new ImsException(e.getMessage(), e.errorCode);
            }
        } catch (RemoteException | IllegalStateException e) {
            throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
@@ -441,10 +436,6 @@ public class ImsMmTelManager {
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
        }
        if (!isImsAvailableOnDevice()) {
            throw new ImsException("IMS not available on device.",
                    ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
        }
        c.setExecutor(executor);
        try {
            getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
@@ -453,7 +444,7 @@ public class ImsMmTelManager {
                // Rethrow as runtime error to keep API compatible.
                throw new IllegalArgumentException(e.getMessage());
            } else {
                throw new RuntimeException(e.getMessage());
                throw new ImsException(e.getMessage(), e.errorCode);
            }
        } catch (RemoteException e) {
            throw e.rethrowAsRuntimeException();
@@ -617,6 +608,46 @@ public class ImsMmTelManager {
        }
    }

    /**
     * Query whether or not the requested MmTel capability is supported by the carrier on the
     * specified network transport.
     * <p>
     * This is a configuration option and does not change. The only time this may change is if a
     * new IMS configuration is loaded when there is a
     * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription.
     * @param capability The capability that is being queried for support on the carrier network.
     * @param transportType The transport type of the capability to check support for.
     * @param callback A consumer containing a Boolean result specifying whether or not the
     *                 capability is supported on this carrier network for the transport specified.
     * @param executor The executor that the callback will be called with.
     * @throws ImsException if the subscription is no longer valid or the IMS service is not
     * available.
     */
    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
    public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
            @AccessNetworkConstants.TransportType int transportType,
            @NonNull Consumer<Boolean> callback,
            @NonNull @CallbackExecutor Executor executor) throws ImsException {
        if (callback == null) {
            throw new IllegalArgumentException("Must include a non-null Consumer.");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
        }
        try {
            getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
                @Override
                public void accept(int result) {
                    executor.execute(() -> callback.accept(result == 1));
                }
            }, capability, transportType);
        } catch (ServiceSpecificException sse) {
            throw new ImsException(sse.getMessage(), sse.errorCode);
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
    }

    /**
     * The user's setting for whether or not they have enabled the "Video Calling" setting.
     *
@@ -940,7 +971,7 @@ public class ImsMmTelManager {
     * @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
     */
    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
    boolean isTtyOverVolteEnabled() {
    public boolean isTtyOverVolteEnabled() {
        try {
            return getITelephony().isTtyOverVolteEnabled(mSubId);
        } catch (ServiceSpecificException e) {
@@ -955,20 +986,39 @@ public class ImsMmTelManager {
        }
    }

    private static boolean isImsAvailableOnDevice() {
        IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
        if (pm == null) {
            // For some reason package manger is not available.. This will fail internally anyways,
            // so do not throw error and allow.
            return true;
    /**
     * Get the status of the MmTel Feature registered on this subscription.
     * @param callback A callback containing an Integer describing the current state of the
     *                 MmTel feature, Which will be one of the following:
     *                 {@link ImsFeature#STATE_UNAVAILABLE},
     *                {@link ImsFeature#STATE_INITIALIZING},
     *                {@link ImsFeature#STATE_READY}. Will be called using the executor
     *                 specified when the service state has been retrieved from the IMS service.
     * @param executor The executor that will be used to call the callback.
     * @throws ImsException if the IMS service associated with this subscription is not available or
     * the IMS service is not available.
     */
    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
    public void getFeatureState(@NonNull @ImsFeature.ImsState Consumer<Integer> callback,
            @NonNull @CallbackExecutor Executor executor) throws ImsException {
        if (callback == null) {
            throw new IllegalArgumentException("Must include a non-null Consumer.");
        }
        if (executor == null) {
            throw new IllegalArgumentException("Must include a non-null Executor.");
        }
        try {
            return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
            getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() {
                @Override
                public void accept(int result) {
                    executor.execute(() -> callback.accept(result));
                }
            });
        } catch (ServiceSpecificException sse) {
            throw new ImsException(sse.getMessage(), sse.errorCode);
        } catch (RemoteException e) {
            // For some reason package manger is not available.. This will fail internally anyways,
            // so do not throw error and allow.
            e.rethrowAsRuntimeException();
        }
        return true;
    }

    private static ITelephony getITelephony() {
+21 −0
Original line number Diff line number Diff line
@@ -362,6 +362,25 @@ public class MmTelFeature extends ImsFeature {
    @Retention(RetentionPolicy.SOURCE)
    public @interface ProcessCallResult {}

    /**
     * If the flag is present and true, it indicates that the incoming call is for USSD.
     * <p>
     * This is an optional boolean flag.
     */
    public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";

    /**
     * If this flag is present and true, this call is marked as an unknown dialing call instead
     * of an incoming call. An example of such a call is a call that is originated by sending
     * commands (like AT commands) directly to the modem without Android involvement or dialing
     * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in
     * certain situations.
     * <p>
     * This is an optional boolean flag.
     */
    public static final String EXTRA_IS_UNKNOWN_CALL =
            "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";

    private IImsMmTelListener mListener;

    /**
@@ -410,6 +429,8 @@ public class MmTelFeature extends ImsFeature {
    /**
     * Notify the framework of an incoming call.
     * @param c The {@link ImsCallSessionImplBase} of the new incoming call.
     * @param extras A bundle containing extra parameters related to the call. See
     * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above.
     */
    public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
            @NonNull Bundle extras) {
+11 −0
Original line number Diff line number Diff line
@@ -866,6 +866,11 @@ interface ITelephony {
    */
    String getImsService(int slotId, boolean isCarrierImsService);

    /**
     * Get the MmTelFeature state attached to this subscription id.
     */
    void getImsMmTelFeatureState(int subId, IIntegerConsumer callback);

    /**
     * Set the network selection mode to automatic.
     *
@@ -1814,6 +1819,12 @@ interface ITelephony {
     */
    boolean isAvailable(int subId, int capability, int regTech);

    /**
     * Return whether or not the MmTel capability is supported for the requested transport type.
     */
    void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
            int transportType);

    /**
     * Returns true if the user's setting for 4G LTE is enabled, for the subscription specified.
     */