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

Commit ffd910d9 authored by Brad Ebinger's avatar Brad Ebinger Committed by Gerrit Code Review
Browse files

Merge "Push Binder updates when ImsFeatures change"

parents d618ad8f 851c9b40
Loading
Loading
Loading
Loading
+29 −13
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import com.android.telephony.Rlog;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
@@ -55,10 +56,19 @@ import java.util.concurrent.atomic.AtomicInteger;
public class ImsSmsDispatcher extends SMSDispatcher {

    private static final String TAG = "ImsSmsDispatcher";
    private static final int CONNECT_DELAY_MS = 5000; // 5 seconds;

    /**
     * Creates FeatureConnector instances for ImsManager, used during testing to inject mock
     * connector instances.
     */
    @VisibleForTesting
    public interface FeatureConnectorFactory {
        FeatureConnector<ImsManager> create(Context context, int phoneId,
                FeatureConnector.Listener<ImsManager> listener, String logPrefix);
        /**
         * Create a new FeatureConnector for ImsManager.
         */
        FeatureConnector<ImsManager> create(Context context, int phoneId, String logPrefix,
                FeatureConnector.Listener<ImsManager> listener, Executor executor);
    }

    @VisibleForTesting
@@ -75,6 +85,13 @@ public class ImsSmsDispatcher extends SMSDispatcher {
    private ImsManager mImsManager;
    private FeatureConnectorFactory mConnectorFactory;

    private Runnable mConnectRunnable = new Runnable() {
        @Override
        public void run() {
            mImsManagerConnector.connect();
        }
    };

    /**
     * Listen to the IMS service state change
     *
@@ -246,14 +263,8 @@ public class ImsSmsDispatcher extends SMSDispatcher {
        super(phone, smsDispatchersController);
        mConnectorFactory = factory;

        mImsManagerConnector = mConnectorFactory.create(mContext, mPhone.getPhoneId(),
        mImsManagerConnector = mConnectorFactory.create(mContext, mPhone.getPhoneId(), TAG,
                new FeatureConnector.Listener<ImsManager>() {
                    @Override
                    public ImsManager getFeatureManager() {
                        return ImsManager.getInstance(mContext, phone.getPhoneId());
                    }

                    @Override
                    public void connectionReady(ImsManager manager) throws ImsException {
                        logd("ImsManager: connection ready.");
                        synchronized (mLock) {
@@ -264,15 +275,20 @@ public class ImsSmsDispatcher extends SMSDispatcher {
                    }

                    @Override
                    public void connectionUnavailable() {
                        logd("ImsManager: connection unavailable.");
                    public void connectionUnavailable(int reason) {
                        logd("ImsManager: connection unavailable, reason=" + reason);
                        if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
                            loge("connectionUnavailable: unexpected, received server error");
                            removeCallbacks(mConnectRunnable);
                            postDelayed(mConnectRunnable, CONNECT_DELAY_MS);
                        }
                        synchronized (mLock) {
                            mImsManager = null;
                            mIsImsServiceUp = false;
                        }
                    }
                }, "ImsSmsDispatcher");
        mImsManagerConnector.connect();
                }, this::post);
        post(mConnectRunnable);
    }

    private void setListeners() throws ImsException {
+2 −2
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;

import com.android.ims.FeatureConnector;
import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
@@ -140,7 +140,7 @@ public class SmsDispatchersController extends Handler {

        // Create dispatchers, inbound SMS handlers and
        // broadcast undelivered messages in raw table.
        mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, FeatureConnector::new);
        mImsSmsDispatcher = new ImsSmsDispatcher(phone, this, ImsManager::getConnector);
        mCdmaDispatcher = new CdmaSMSDispatcher(phone, this);
        mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
                storageMonitor, phone);
+2 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.system.StructStatVfs;
import android.telephony.AccessNetworkConstants.TransportType;
import android.text.TextUtils;

import com.android.ims.ImsManager;
import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
import com.android.internal.telephony.cdma.EriManager;
import com.android.internal.telephony.dataconnection.DataEnabledSettings;
@@ -375,7 +376,7 @@ public class TelephonyComponentFactory {
    }

    public ImsPhoneCallTracker makeImsPhoneCallTracker(ImsPhone imsPhone) {
        return new ImsPhoneCallTracker(imsPhone);
        return new ImsPhoneCallTracker(imsPhone, ImsManager::getConnector);
    }

    public ImsExternalCallTracker makeImsExternalCallTracker(ImsPhone imsPhone) {
+54 −107
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
@@ -40,8 +41,6 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
@@ -52,6 +51,9 @@ import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;

import com.android.ims.FeatureConnector;
import com.android.ims.ImsFeatureBinderRepository;
import com.android.ims.ImsFeatureContainer;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -83,7 +85,7 @@ import java.util.stream.Collectors;
 * 2. Device overlay default value (including no SIM case).
 *
 * ImsManager can then retrieve the binding to the correct ImsService using
 * {@link #getImsServiceControllerAndListen} on a per-slot and per feature basis.
 * {@link #listenForFeature} on a per-slot and per feature basis.
 */

public class ImsResolver implements ImsServiceController.ImsServiceControllerCallbacks {
@@ -342,7 +344,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
         * @return the ImsServiceController created using the context and componentName supplied.
         */
        ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks);
                ImsServiceController.ImsServiceControllerCallbacks callbacks,
                ImsFeatureBinderRepository repo);
    }

    private ImsServiceControllerFactory mImsServiceControllerFactory =
@@ -355,8 +358,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

        @Override
        public ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks) {
            return new ImsServiceController(context, componentName, callbacks);
                ImsServiceController.ImsServiceControllerCallbacks callbacks,
                ImsFeatureBinderRepository repo) {
            return new ImsServiceController(context, componentName, callbacks, repo);
        }
    };

@@ -378,8 +382,9 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal

                @Override
                public ImsServiceController create(Context context, ComponentName componentName,
                        ImsServiceController.ImsServiceControllerCallbacks callbacks) {
                    return new ImsServiceControllerCompat(context, componentName, callbacks);
                        ImsServiceController.ImsServiceControllerCallbacks callbacks,
                        ImsFeatureBinderRepository repo) {
                    return new ImsServiceControllerCompat(context, componentName, callbacks, repo);
                }
            };

@@ -393,6 +398,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    // registered through, so we must retain the Context as long as we need the receiver to be
    // active.
    private final Context mReceiverContext;
    private final ImsFeatureBinderRepository mRepo;
    // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from
    // ImsServiceController callbacks.
    private final Object mBoundServicesLock = new Object();
@@ -477,6 +483,8 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        return true;
    });

    private HandlerExecutor mRunnableExecutor = new HandlerExecutor(mHandler);

    // Results from dynamic queries to ImsService regarding the features they support.
    private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener =
            new ImsServiceFeatureQueryManager.Listener() {
@@ -520,11 +528,12 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
    private ImsServiceFeatureQueryManager mFeatureQueryManager;

    public ImsResolver(Context context, String defaultMmTelPackageName,
            String defaultRcsPackageName, int numSlots) {
            String defaultRcsPackageName, int numSlots, ImsFeatureBinderRepository repo) {
        Log.i(TAG, "device MMTEL package: " + defaultMmTelPackageName + ", device RCS package:"
                + defaultRcsPackageName);
        mContext = context;
        mNumSlots = numSlots;
        mRepo = repo;
        mReceiverContext = context.createContextAsUser(UserHandle.ALL, 0 /*flags*/);

        mCarrierServices = new SparseArray<>(mNumSlots);
@@ -670,76 +679,20 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
    }

    /**
     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id or {@link null} if
     * the service is not available. If an IImsMMTelFeature is available, the
     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
     * @param callback Listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsMmTelFeature} interface or {@link null} if it is unavailable.
     */
    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.FEATURE_MMTEL, callback);
        return (controller != null) ? controller.getMmTelFeature(slotId) : null;
    }

    /**
     * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for emergency
     * calling or {@link null} if the service is not available. If an IImsMMTelFeature is
     * available, the {@link IImsServiceFeatureCallback} callback is registered as a listener for
     * feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsRcsFeature} for.
     * @param callback listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsRcsFeature} interface or {@link null} if it is unavailable.
     */
    public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.FEATURE_RCS, callback);
        return (controller != null) ? controller.getRcsFeature(slotId) : null;
    }

    /**
     * Returns the ImsRegistration structure associated with the slotId and feature specified.
     */
    public @Nullable IImsRegistration getImsRegistration(int slotId, int feature)
            throws RemoteException {
        ImsServiceController controller = getImsServiceController(slotId, feature);
        if (controller != null) {
            return controller.getRegistration(slotId);
        }
        return null;
    public @Nullable IImsRegistration getImsRegistration(int slotId, int feature) {
        ImsFeatureContainer fc = mRepo.getIfExists(slotId, feature).orElse(null);
        return  (fc != null) ? fc.imsRegistration : null;
    }

    /**
     * Returns the ImsConfig structure associated with the slotId and feature specified.
     */
    public @Nullable IImsConfig getImsConfig(int slotId, int feature)
            throws RemoteException {
        ImsServiceController controller = getImsServiceController(slotId, feature);
        if (controller != null) {
            return controller.getConfig(slotId);
        }
        return null;
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceController(int slotId, int feature) {
        if (slotId < 0 || slotId >= mNumSlots) {
            return null;
        }
        ImsServiceController controller;
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                return null;
            }
            controller = services.get(feature);
        }
        return controller;
    public @Nullable IImsConfig getImsConfig(int slotId, int feature) {
        ImsFeatureContainer fc = mRepo.getIfExists(slotId, feature).orElse(null);
        return  (fc != null) ? fc.imsConfig : null;
    }

    private  SparseArray<ImsServiceController> getImsServiceControllers(int slotId) {
@@ -755,32 +708,36 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceController(slotId, feature);
    /**
     * Register a new listener for the feature type and slot specified. ImsServiceController will
     * update the connections as they become available.
     */
    public void listenForFeature(int slotId, int feature, IImsServiceFeatureCallback callback) {
        mRepo.registerForConnectionUpdates(slotId, feature, callback, mRunnableExecutor);
    }

        if (controller != null) {
            controller.addImsServiceFeatureCallback(callback);
            return controller;
    /**
     * Do not set up a persistent callback, but rather call back once depending on if the feature
     * requested exists.
     */
    public void callBackIfExists(int slotId, int feature, IImsServiceFeatureCallback callback) {
        ImsFeatureContainer c = mRepo.getIfExists(slotId, feature).orElse(null);
        try {
            if (c != null) {
                callback.imsFeatureCreated(c);
            } else {
                callback.imsFeatureRemoved(FeatureConnector.UNAVAILABLE_REASON_DISCONNECTED);
            }
        return null;
        } catch (RemoteException ignore) { } //remote is dead.
    }

    /**
     * Unregister a previously registered IImsServiceFeatureCallback through
     * {@link #getImsServiceControllerAndListen(int, int, IImsServiceFeatureCallback)} .
     * @param slotId The slot id associated with the ImsFeature.
     * @param feature The {@link ImsFeature.FeatureType}
     * {@link #listenForFeature(int, int, IImsServiceFeatureCallback)}.
     * @param callback The callback to be unregistered.
     */
    public void unregisterImsFeatureCallback(int slotId, int feature,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceController(slotId, feature);

        if (controller != null) {
            controller.removeImsServiceFeatureCallback(callback);
        }
    public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
        mRepo.unregisterForConnectionUpdates(callback);
    }

    // Used for testing only.
@@ -1057,7 +1014,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
                    Log.w(TAG, "bindImsService: error=" + e.getMessage());
                }
            } else {
                controller = info.controllerFactory.create(mContext, info.name, this);
                controller = info.controllerFactory.create(mContext, info.name, this, mRepo);
                Log.i(TAG, "Binding ImsService: " + controller.getComponentName()
                        + " with features: " + features);
                controller.bind(features);
@@ -1124,6 +1081,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
     * {@link ImsServiceController.ImsServiceControllerCallbacks#imsServiceFeatureCreated}, which
     * removes the ImsServiceController from the mBoundImsServicesByFeature structure.
     */
    @Override
    public void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller) {
        putImsController(slotId, feature, controller);
    }
@@ -1133,6 +1091,7 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
     * {@link ImsServiceController.ImsServiceControllerCallbacks#imsServiceFeatureRemoved}, which
     * removes the ImsServiceController from the mBoundImsServicesByFeature structure.
     */
    @Override
    public void imsServiceFeatureRemoved(int slotId, int feature, ImsServiceController controller) {
        removeImsController(slotId, feature);
    }
@@ -1631,22 +1590,6 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
        }
        pw.decreaseIndent();
        pw.decreaseIndent();
        pw.println("Bound Features:");
        pw.increaseIndent();
        for (int i = 0; i < mNumSlots; i++) {
            for (int j = 0; j < MmTelFeature.FEATURE_MAX; j++) {
                pw.print("slot=");
                pw.print(i);
                pw.print(", feature=");
                pw.print(ImsFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
                pw.println(": ");
                pw.increaseIndent();
                ImsServiceController c = getImsServiceController(i, j);
                pw.println(c == null ? "none" : c);
                pw.decreaseIndent();
            }
        }
        pw.decreaseIndent();
        pw.println("Cached ImsServices:");
        pw.increaseIndent();
        for (ImsServiceInfo i : mInstalledServicesCache.values()) {
@@ -1662,6 +1605,10 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
            pw.decreaseIndent();
        }
        pw.decreaseIndent();
        pw.println("Connection Repository Log:");
        pw.increaseIndent();
        mRepo.dump(pw);
        pw.decreaseIndent();
        pw.println("Event Log:");
        pw.increaseIndent();
        mEventLog.dump(pw);
+65 −186

File changed.

Preview size limit exceeded, changes collapsed.

Loading