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

Commit 512858e1 authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Increase ImsManager efficiency when using getInstance

1) Remove FeatureConnector "oneshot" idea, instead always
use the normal #connect method.

2) FeatureConnector should not call back while holding lock.

3) ImsManager#getInstance has been reworked to increase efficiency.
Instead of creating a new ImsManager every time getInstance is called,
create one ImsManager per slot and share it amongst all users. This
is due to ImsManager being a pretty "heavyweight" object (may spawn
threads). In order to accomplish this with the new FeatureConnector,
each ImsManager will be contained in a static InstanceManager class,
which will manage internally updating the MmTelFeatureConnection for
the ImsManager instance as it is updated.

Test: atest ImsCommonTests
Change-Id: Idc56628ea7b6cf705ce55d163ea29e5807a2515c
parent 7359b5b5
Loading
Loading
Loading
Loading
+34 −50
Original line number Diff line number Diff line
@@ -135,32 +135,37 @@ public class FeatureConnector<U extends FeatureUpdates> {
                    log("imsFeatureRemoved: ignore");
                    return;
                }
                mManager.invalidate();
                mDisconnectedReason = reason;
                // Ensure that we set ready state back to false so that we do not miss setting ready
                // later if the initial state when recreated is READY.
                mLastReadyState = false;
            }
            // Allow the listener to do cleanup while the connection still potentially valid (unless
            // the process crashed).
            mExecutor.execute(() -> mListener.connectionUnavailable(reason));
            mManager.invalidate();
        }

        @Override
        public void imsStatusChanged(int status) {
            log("imsStatusChanged: status=" + ImsFeature.STATE_LOG_MAP.get(status));
            final U manager;
            final boolean isReady;
            synchronized (mLock) {
                if (mDisconnectedReason != null) {
                    log("imsStatusChanged: ignore");
                    return;
                }
                mManager.updateFeatureState(status);
                final U manager = mManager;
                final boolean isReady = mReadyFilter.contains(status);
                manager = mManager;
                isReady = mReadyFilter.contains(status);
                boolean didReadyChange = isReady ^ mLastReadyState;
                mLastReadyState = isReady;
                if (!didReadyChange) {
                    log("imsStatusChanged: ready didn't change, ignore");
                    return;
                }
            }
            mExecutor.execute(() -> {
                try {
                    if (isReady) {
@@ -178,7 +183,6 @@ public class FeatureConnector<U extends FeatureUpdates> {
                }
            });
        }
        }

        @Override
        public void updateCapabilities(long caps) {
@@ -208,8 +212,6 @@ public class FeatureConnector<U extends FeatureUpdates> {
    private U mManager;
    // Start in disconnected state;
    private Integer mDisconnectedReason = UNAVAILABLE_REASON_DISCONNECTED;
    // Record state to cut down on logging
    private boolean mIsOneShot = false;
    // Stop redundant connectionAvailable if the ready filter contains multiple states.
    // Also, do not send the first unavailable until after we have moved to available once.
    private boolean mLastReadyState = false;
@@ -245,29 +247,11 @@ public class FeatureConnector<U extends FeatureUpdates> {
            return;
        }
        synchronized (mLock) {
            mIsOneShot = false;
            if (mManager == null) {
                mManager = mFactory.createManager(mContext, mPhoneId);
            }
            mManager.registerFeatureCallback(mPhoneId, mCallback, false /*oneShot*/);
        }
    }

    public void connectForOneShot() {
        if (DBG) log("connectForOneShot");
        if (!isSupported()) {
            mExecutor.execute(() -> mListener.connectionUnavailable(
                    UNAVAILABLE_REASON_IMS_UNSUPPORTED));
            logw("connectForOneShot: not supported.");
            return;
        }
        synchronized (mLock) {
            mIsOneShot = true;
            if (mManager == null) {
                mManager = mFactory.createManager(mContext, mPhoneId);
            }
            mManager.registerFeatureCallback(mPhoneId, mCallback, true /*oneShot*/);
        }
        mManager.registerFeatureCallback(mPhoneId, mCallback);
    }

    // Check if this ImsFeature is supported or not.
@@ -281,13 +265,17 @@ public class FeatureConnector<U extends FeatureUpdates> {
     */
    public void disconnect() {
        if (DBG) log("disconnect");
        final U manager;
        synchronized (mLock) {
            mManager.unregisterFeatureCallback(mCallback);
            manager = mManager;
        }
        if (manager == null) return;

        manager.unregisterFeatureCallback(mCallback);
        try {
            mCallback.imsFeatureRemoved(UNAVAILABLE_REASON_DISCONNECTED);
        } catch (RemoteException ignore) {} // local call
    }
    }

    // Should be called on executor
    private void notifyReady(U manager) throws ImsException {
@@ -307,15 +295,11 @@ public class FeatureConnector<U extends FeatureUpdates> {
        mListener.connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
    }

    private final void log(String message) {
        // cut down on log spam
        synchronized (mLock) {
            if (mIsOneShot) return;
        }
    private void log(String message) {
        Rlog.d(TAG, "[" + mLogPrefix + ", " + mPhoneId + "] " + message);
    }

    private final void logw(String message) {
    private void logw(String message) {
        Rlog.w(TAG, "[" + mLogPrefix + ", " + mPhoneId + "] " + message);
    }
}
+2 −4
Original line number Diff line number Diff line
@@ -30,15 +30,13 @@ import com.android.ims.internal.IImsServiceFeatureCallback;
 */
public interface FeatureUpdates {
    /**
     * Register a calback for the slot specified so that the FeatureConnector can notify its
     * Register a callback for the slot specified so that the FeatureConnector can notify its
     * listener of changes.
     * @param slotId The slot the callback is registered for.
     * @param cb The callback that the FeatureConnector will use to update its state and notify
     *           its callback of changes.
     * @param oneShot True if this callback should only be registered for one update (feature is
     *                available or not), false if this listener should be persistent.
     */
    void registerFeatureCallback(int slotId, IImsServiceFeatureCallback cb, boolean oneShot);
    void registerFeatureCallback(int slotId, IImsServiceFeatureCallback cb);

    /**
     * Unregister a previously registered callback due to the FeatureConnector disconnecting.
+230 −176

File changed.

Preview size limit exceeded, changes collapsed.

+16 −16
Original line number Diff line number Diff line
@@ -215,12 +215,8 @@ public class MmTelFeatureConnection extends FeatureConnection {

    @Override
    protected void onRemovedOrDied() {
        synchronized (mLock) {
        closeConnection();
        super.onRemovedOrDied();
            mRegistrationCallbackManager.close();
            mCapabilityCallbackManager.close();
            mProvisioningCallbackManager.close();
        }
    }

    public boolean isEmergencyMmTelAvailable() {
@@ -241,11 +237,14 @@ public class MmTelFeatureConnection extends FeatureConnection {
        }
    }

    /**
     * Clean up all caches as well as any callbacks that are currently associated with the
     * MmTelFeature.
     */
    public void closeConnection() {
        mRegistrationCallbackManager.close();
        mCapabilityCallbackManager.close();
        mProvisioningCallbackManager.close();
        try {
        synchronized (mLock) {
            if (mUt != null) {
                mUt.close();
@@ -253,14 +252,15 @@ public class MmTelFeatureConnection extends FeatureConnection {
            }
            mEcbm = null;
            mMultiEndpoint = null;
            try {
                if (isBinderAlive()) {
                    getServiceInterface(mBinder).setListener(null);
                }
            }
            } catch (RemoteException e) {
                Log.w(TAG + " [" + mSlotId + "]", "closeConnection: couldn't remove listener!");
            }
        }
    }

    public void addRegistrationCallback(IImsRegistrationCallback callback) {
        mRegistrationCallbackManager.addCallback(callback);
+2 −4
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ public class RcsFeatureConnection extends FeatureConnection {
    public RcsFeatureConnection(Context context, int slotId, IImsRcsFeature feature, IImsConfig c,
            IImsRegistration r) {
        super(context, slotId, c, r);
        setBinder(feature.asBinder());
        setBinder(feature != null ? feature.asBinder() : null);
        mAvailabilityCallbackManager = new AvailabilityCallbackManager(mContext);
        mRegistrationCallbackManager = new RegistrationCallbackManager(mContext);
    }
@@ -132,10 +132,8 @@ public class RcsFeatureConnection extends FeatureConnection {

    @Override
    protected void onRemovedOrDied() {
        super.onRemovedOrDied();
        synchronized (mLock) {
        close();
        }
        super.onRemovedOrDied();
    }

    public void setRcsFeatureListener(IRcsFeatureListener listener) throws RemoteException {
Loading