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

Commit 1e61c45c authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Move to a push model of querying ImsFeature Binders

[RESUBMISSION AFTER REVERT aosp/1426022]

Instead of a polling model, allow listeners to instead
listen for updates to a specific ImsFeature interface
and get notified when they are available.

FeatureConnectionRepository is used by the ImsServiceControllers
to store new MMTEL and RCS feature binders along with the
associated IMS config and registration interfaces that should be
used along with them. Listeners can then register for updates to
the ImsFeatures, including changes to capabilities and state.

The FeatureConnector has also been refactored to listen ann
update MmTel and RCS FeatureConnections in the ImsManager and
RcsFeatureManager instances as Binders become
available/unavailable or change when new SIM cards are
inserted/removed instead of using a polling method of
retrieving Binder instances.

Fixes: 169864814
Test: atest ImsCommonTests
Merged-In: Ie35b443ee2734c72f52d736f3980c1521a958d96
Change-Id: Ie35b443ee2734c72f52d736f3980c1521a958d96
parent 635f3621
Loading
Loading
Loading
Loading
+29 −146
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.ims;

import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
@@ -29,11 +28,7 @@ import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;

import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.util.HandlerExecutor;

import java.util.concurrent.Executor;

/**
 * Base class of MmTelFeatureConnection and RcsFeatureConnection.
@@ -41,51 +36,26 @@ import java.util.concurrent.Executor;
public abstract class FeatureConnection {
    protected static final String TAG = "FeatureConnection";

    public interface IFeatureUpdate {
        /**
         * Called when the ImsFeature has changed its state. Use
         * {@link ImsFeature#getFeatureState()} to get the new state.
         */
        void notifyStateChanged();

        /**
         * Called when the ImsFeature has become unavailable due to the binder switching or app
         * crashing. A new ImsServiceProxy should be requested for that feature.
         */
        void notifyUnavailable();
    }

    protected static boolean sImsSupportedOnDevice = true;

    protected final int mSlotId;
    protected Context mContext;
    protected IBinder mBinder;
    @VisibleForTesting
    public Executor mExecutor;

    // We are assuming the feature is available when started.
    protected volatile boolean mIsAvailable = true;
    // ImsFeature Status from the ImsService. Cached.
    protected Integer mFeatureStateCached = null;
    protected IFeatureUpdate mStatusCallback;
    protected IImsRegistration mRegistrationBinder;
    protected IImsConfig mConfigBinder;
    protected long mFeatureCapabilities;
    private final IImsRegistration mRegistrationBinder;
    private final IImsConfig mConfigBinder;
    protected final Object mLock = new Object();

    public FeatureConnection(Context context, int slotId) {
    public FeatureConnection(Context context, int slotId, IImsConfig c, IImsRegistration r) {
        mSlotId = slotId;
        mContext = context;

        // Callbacks should be scheduled on the main thread.
        if (context.getMainLooper() != null) {
            mExecutor = context.getMainExecutor();
        } else {
            // Fallback to the current thread.
            if (Looper.myLooper() == null) {
                Looper.prepare();
            }
            mExecutor = new HandlerExecutor(new Handler(Looper.myLooper()));
        }
        mRegistrationBinder = r;
        mConfigBinder = c;
    }

    protected TelephonyManager getTelephonyManager() {
@@ -128,57 +98,12 @@ public abstract class FeatureConnection {
        synchronized (mLock) {
            if (mIsAvailable) {
                mIsAvailable = false;
                mRegistrationBinder = null;
                if (mBinder != null) {
                    mBinder.unlinkToDeath(mDeathRecipient, 0);
                }
                if (mStatusCallback != null) {
                    Log.d(TAG, "onRemovedOrDied: notifyUnavailable");
                    mStatusCallback.notifyUnavailable();
                    // Unlink because this FeatureConnection should no longer send callbacks.
                    mStatusCallback = null;
                }
            }
        }
    }

    /**
     * The listener for ImsManger and RcsFeatureManager to receive IMS feature status changed.
     * @param callback Callback that will fire when the feature status has changed.
     */
    public void setStatusCallback(IFeatureUpdate callback) {
        mStatusCallback = callback;
            }

    @VisibleForTesting
    public IImsServiceFeatureCallback getListener() {
        return mListenerBinder;
        }

    /**
     * The callback to receive ImsFeature status changed.
     */
    private final IImsServiceFeatureCallback mListenerBinder =
        new IImsServiceFeatureCallback.Stub() {
            @Override
            public void imsFeatureCreated(int slotId, int feature) {
                mExecutor.execute(() -> {
                    handleImsFeatureCreatedCallback(slotId, feature);
                });
            }
            @Override
            public void imsFeatureRemoved(int slotId, int feature) {
                mExecutor.execute(() -> {
                    handleImsFeatureRemovedCallback(slotId, feature);
                });
            }
            @Override
            public void imsStatusChanged(int slotId, int feature, int status) {
                mExecutor.execute(() -> {
                    handleImsStatusChangedCallback(slotId, feature, status);
                });
    }
        };

    public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTech()
            throws RemoteException {
@@ -192,41 +117,10 @@ public abstract class FeatureConnection {
    }

    public @Nullable IImsRegistration getRegistration() {
        synchronized (mLock) {
            // null if cache is invalid;
            if (mRegistrationBinder != null) {
                return mRegistrationBinder;
            }
        }
        // We don't want to synchronize on a binder call to another process.
        IImsRegistration regBinder = getRegistrationBinder();
        synchronized (mLock) {
            // mRegistrationBinder may have changed while we tried to get the registration
            // interface.
            if (mRegistrationBinder == null) {
                mRegistrationBinder = regBinder;
            }
        }
        return mRegistrationBinder;
    }

    public @Nullable
    IImsConfig getConfig() {
        synchronized (mLock) {
            // null if cache is invalid;
            if (mConfigBinder != null) {
                return mConfigBinder;
            }
        }
        // We don't want to synchronize on a binder call to another process.
        IImsConfig configBinder = getConfigBinder();
        synchronized (mLock) {
            // mRegistrationBinder may have changed while we tried to get the registration
            // interface.
            if (mConfigBinder == null) {
                mConfigBinder = configBinder;
            }
        }
    public @Nullable IImsConfig getConfig() {
        return mConfigBinder;
    }

@@ -260,6 +154,27 @@ public abstract class FeatureConnection {
        return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
    }

    public void updateFeatureState(int state) {
        synchronized (mLock) {
            mFeatureStateCached = state;
        }
    }

    public long getFeatureCapabilties() {
        synchronized (mLock) {
            return mFeatureCapabilities;
        }
    }

    public void updateFeatureCapabilities(long caps) {
        synchronized (mLock) {
            if (mFeatureCapabilities != caps) {
                mFeatureCapabilities = caps;
                onFeatureCapabilitiesUpdated(caps);
            }
        }
    }

    /**
     * @return an integer describing the current Feature Status, defined in
     * {@link ImsFeature.ImsState}.
@@ -284,42 +199,10 @@ public abstract class FeatureConnection {
        return state;
    }

    /**
     * An ImsFeature has been created for this FeatureConnection for the associated
     * {@link ImsFeature.FeatureType}.
     * @param slotId The slot ID associated with the event.
     * @param feature The {@link ImsFeature.FeatureType} associated with the event.
     */
    protected abstract void handleImsFeatureCreatedCallback(int slotId, int feature);

    /**
     * An ImsFeature has been removed for this FeatureConnection for the associated
     * {@link ImsFeature.FeatureType}.
     * @param slotId The slot ID associated with the event.
     * @param feature The {@link ImsFeature.FeatureType} associated with the event.
     */
    protected abstract void handleImsFeatureRemovedCallback(int slotId, int feature);

    /**
     * The status of an ImsFeature has changed for the associated {@link ImsFeature.FeatureType}.
     * @param slotId The slot ID associated with the event.
     * @param feature The {@link ImsFeature.FeatureType} associated with the event.
     * @param status The new {@link ImsFeature.ImsState} associated with the ImsFeature
     */
    protected abstract void handleImsStatusChangedCallback(int slotId, int feature, int status);

    /**
     * Internal method used to retrieve the feature status from the corresponding ImsService.
     */
    protected abstract Integer retrieveFeatureState();

    /**
     * @return The ImsRegistration instance associated with the FeatureConnection.
     */
    protected abstract IImsRegistration getRegistrationBinder();

    /**
     * @return The ImsRegistration instance associated with the FeatureConnection.
     */
    protected abstract IImsConfig getConfigBinder();
    protected abstract void onFeatureCapabilitiesUpdated(long capabilities);
}
+207 −174

File changed.

Preview size limit exceeded, changes collapsed.

+72 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ims;

import android.os.IBinder;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.ImsFeature;

import com.android.ims.internal.IImsServiceFeatureCallback;

/**
 * Interface used by Manager interfaces that will use a {@link FeatureConnector} to connect to
 * remote ImsFeature Binder interfaces.
 */
public interface FeatureUpdates {
    /**
     * Register a calback 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);

    /**
     * Unregister a previously registered callback due to the FeatureConnector disconnecting.
     * <p>
     * This does not need to be called if the callback was previously registered for a one
     * shot result.
     * @param cb The callback to unregister.
     */
    void unregisterFeatureCallback(IImsServiceFeatureCallback cb);

    /**
     * Associate this Manager instance with the IMS Binder interfaces specified. This is usually
     * done by creating a FeatureConnection instance with these interfaces.
     */
    void associate(IBinder feature, IImsConfig c, IImsRegistration r);

    /**
     * Invalidate the previously associated Binder interfaces set in {@link #associate}.
     */
    void invalidate();

    /**
     * Update the state of the remote ImsFeature associated with this Manager instance.
     */
    void updateFeatureState(@ImsFeature.ImsState int state);

    /**
     * Update the capabilities of the remove ImsFeature associated with this Manager instance.
     */
    void updateFeatureCapabilities(@ImsService.ImsServiceCapability long capabilities);
}
 No newline at end of file
+0 −24
Original line number Diff line number Diff line
/*
 * Copyright (c) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ims;

public interface IFeatureConnector<T> {
    int getImsServiceState() throws ImsException;
    void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate callback)
            throws android.telephony.ims.ImsException;
    void removeNotifyStatusChangedCallback(FeatureConnection.IFeatureUpdate callback);
}
 No newline at end of file
+438 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading