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

Commit bb905fd0 authored by Bryce Lee's avatar Bryce Lee
Browse files

CommunalSource.Connection Introduction

This changelist introduces the Connection interface,
abstracting details around the result reporting mechanism.
It also sets the expectation that the client holds onto
the connection, allowing connectors to build around this
assumption.

The Connection interface also allows connection state
to be contained in a single entity, tied to the primer.
As a result, the CommunalSources no longer need to
track state and maintain their own callbacks.

Test: atest CommunalSourcePrimerTest
Bug: 209607168

Change-Id: I599d1ba421d76ec9e9c20c82718104358929c5e4
parent c42e127f
Loading
Loading
Loading
Loading
+17 −26
Original line number Diff line number Diff line
@@ -35,7 +35,23 @@ public interface CommunalSource {
     * {@link Connector} defines an interface for {@link CommunalSource} instances to be generated.
     */
    interface Connector {
        ListenableFuture<Optional<CommunalSource>> connect();
        Connection connect(Connection.Callback callback);
    }

    /**
     * {@link Connection} defines an interface for an entity which holds the necessary components
     * for establishing and maintaining a connection to the communal source.
     */
    interface Connection {
        /**
         * {@link Callback} defines an interface for clients to be notified when a source is ready
         */
        interface Callback {
            void onSourceEstablished(Optional<CommunalSource> source);
            void onDisconnected();
        }

        void disconnect();
    }

    /**
@@ -86,29 +102,4 @@ public interface CommunalSource {
     * value will be {@code null} in case of a failure.
     */
    ListenableFuture<CommunalViewResult> requestCommunalView(Context context);

    /**
     * Adds a {@link Callback} to receive future status updates regarding this
     * {@link CommunalSource}.
     *
     * @param callback The {@link Callback} to be added.
     */
    void addCallback(Callback callback);

    /**
     * Removes a {@link Callback} from receiving future updates.
     *
     * @param callback The {@link Callback} to be removed.
     */
    void removeCallback(Callback callback);

    /**
     * An interface for receiving updates on the state of the {@link CommunalSource}.
     */
    interface Callback {
        /**
         * Invoked when the {@link CommunalSource} is no longer available for use.
         */
        void onDisconnected();
    }
}
+37 −43
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.communal.conditions.CommunalConditionsMonitor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;

import com.google.android.collect.Lists;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.Executor;

import javax.inject.Inject;

@@ -41,6 +43,7 @@ public class CommunalSourceMonitor {
    // A list of {@link Callback} that have registered to receive updates.
    private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList();
    private final CommunalConditionsMonitor mConditionsMonitor;
    private final Executor mExecutor;

    private CommunalSource mCurrentSource;

@@ -50,14 +53,6 @@ public class CommunalSourceMonitor {
    // Whether the class is currently listening for condition changes.
    private boolean mListeningForConditions = false;

    private CommunalSource.Callback mSourceCallback = new CommunalSource.Callback() {
        @Override
        public void onDisconnected() {
            // Clear source reference.
            setSource(null /* source */);
        }
    };

    private final CommunalConditionsMonitor.Callback mConditionsCallback =
            allConditionsMet -> {
                if (mAllCommunalConditionsMet != allConditionsMet) {
@@ -70,7 +65,9 @@ public class CommunalSourceMonitor {

    @VisibleForTesting
    @Inject
    public CommunalSourceMonitor(CommunalConditionsMonitor communalConditionsMonitor) {
    public CommunalSourceMonitor(@Main Executor executor,
            CommunalConditionsMonitor communalConditionsMonitor) {
        mExecutor = executor;
        mConditionsMonitor = communalConditionsMonitor;
    }

@@ -81,23 +78,15 @@ public class CommunalSourceMonitor {
     * @param source The new {@link CommunalSource}.
     */
    public void setSource(CommunalSource source) {
        if (mCurrentSource != null) {
            mCurrentSource.removeCallback(mSourceCallback);
        }

        mCurrentSource = source;

        if (mAllCommunalConditionsMet) {
            executeOnSourceAvailableCallbacks();
        }

        // Add callback to be informed when the source disconnects.
        if (mCurrentSource != null) {
            mCurrentSource.addCallback(mSourceCallback);
        }
    }

    private void executeOnSourceAvailableCallbacks() {
        mExecutor.execute(() -> {
            // If the new source is valid, inform registered Callbacks of its presence.
            Iterator<WeakReference<Callback>> itr = mCallbacks.iterator();
            while (itr.hasNext()) {
@@ -106,10 +95,11 @@ public class CommunalSourceMonitor {
                    itr.remove();
                } else {
                    cb.onSourceAvailable(
                        (mAllCommunalConditionsMet && mCurrentSource != null) ? new WeakReference<>(
                                mCurrentSource) : null);
                            (mAllCommunalConditionsMet && mCurrentSource != null)
                                    ? new WeakReference<>(mCurrentSource) : null);
                }
            }
        });
    }

    /**
@@ -118,6 +108,7 @@ public class CommunalSourceMonitor {
     * @param callback The {@link Callback} to add.
     */
    public void addCallback(Callback callback) {
        mExecutor.execute(() -> {
            mCallbacks.add(new WeakReference<>(callback));

            // Inform the callback of any already present CommunalSource.
@@ -129,6 +120,7 @@ public class CommunalSourceMonitor {
                mConditionsMonitor.addCallback(mConditionsCallback);
                mListeningForConditions = true;
            }
        });
    }

    /**
@@ -137,12 +129,14 @@ public class CommunalSourceMonitor {
     * @param callback The {@link Callback} to add.
     */
    public void removeCallback(Callback callback) {
        mExecutor.execute(() -> {
            mCallbacks.removeIf(el -> el.get() == callback);

            if (mCallbacks.isEmpty() && mListeningForConditions) {
                mConditionsMonitor.removeCallback(mConditionsCallback);
                mListeningForConditions = false;
            }
        });
    }

    /**
+29 −24
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.time.SystemClock;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.Optional;

import javax.inject.Inject;
@@ -53,10 +51,11 @@ public class CommunalSourcePrimer extends CoreStartable {

    private int mReconnectAttempts = 0;
    private Runnable mCurrentReconnectCancelable;
    private ListenableFuture<Optional<CommunalSource>> mGetSourceFuture;

    private final Optional<CommunalSource.Connector> mConnector;
    private final Optional<CommunalSource.Observer> mObserver;
    private final Optional<CommunalSource.Connector> mConnector;

    private CommunalSource.Connection mCurrentConnection;

    private final Runnable mConnectRunnable = new Runnable() {
        @Override
@@ -66,6 +65,10 @@ public class CommunalSourcePrimer extends CoreStartable {
        }
    };

    private final CommunalSource.Observer.Callback mObserverCallback = () -> {
        initiateConnectionAttempt();
    };

    @Inject
    public CommunalSourcePrimer(Context context, @Main Resources resources,
            SystemClock clock,
@@ -132,7 +135,7 @@ public class CommunalSourcePrimer extends CoreStartable {
    @Override
    protected void onBootCompleted() {
        if (mObserver.isPresent()) {
            mObserver.get().addCallback(() -> initiateConnectionAttempt());
            mObserver.get().addCallback(mObserverCallback);
        }
        initiateConnectionAttempt();
    }
@@ -142,34 +145,36 @@ public class CommunalSourcePrimer extends CoreStartable {
            Log.d(TAG, "attempting to communal to communal source");
        }

        if (mGetSourceFuture != null) {
        if (mCurrentConnection != null) {
            if (DEBUG) {
                Log.d(TAG, "canceling in-flight connection");
            }
            mGetSourceFuture.cancel(true);
            mCurrentConnection.disconnect();
        }

        mGetSourceFuture = mConnector.get().connect();
        mGetSourceFuture.addListener(() -> {
            try {
                final long startTime = mSystemClock.currentTimeMillis();
                Optional<CommunalSource> result = mGetSourceFuture.get();
                if (result.isPresent()) {
                    final CommunalSource source = result.get();
                    source.addCallback(() -> {
                        if (mSystemClock.currentTimeMillis() - startTime > mMinConnectionDuration) {
                            initiateConnectionAttempt();
        mCurrentConnection = mConnector.get().connect(new CommunalSource.Connection.Callback() {
            private long mStartTime;

            @Override
            public void onSourceEstablished(Optional<CommunalSource> optionalSource) {
                mStartTime = mSystemClock.currentTimeMillis();

                if (optionalSource.isPresent()) {
                    final CommunalSource source = optionalSource.get();
                    mMonitor.setSource(source);
                } else {
                    scheduleConnectionAttempt();
                }
                    });
                    mMonitor.setSource(source);
            }

            @Override
            public void onDisconnected() {
                if (mSystemClock.currentTimeMillis() - mStartTime > mMinConnectionDuration) {
                    initiateConnectionAttempt();
                } else {
                    scheduleConnectionAttempt();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, mMainExecutor);
        });
    }
}
+0 −7
Original line number Diff line number Diff line
@@ -519,8 +519,6 @@ public class NotificationPanelViewController extends PanelViewController {

    private WeakReference<CommunalSource> mCommunalSource;

    private final CommunalSource.Callback mCommunalSourceCallback;

    private final CommandQueue mCommandQueue;
    private final NotificationLockscreenUserManager mLockscreenUserManager;
    private final UserManager mUserManager;
@@ -906,9 +904,6 @@ public class NotificationPanelViewController extends PanelViewController {

        mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
        mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition());
        mCommunalSourceCallback = () -> {
            mUiExecutor.execute(() -> setCommunalSource(null /*source*/));
        };

        mCommunalSourceMonitorCallback = (source) -> {
            mUiExecutor.execute(() -> setCommunalSource(source));
@@ -4719,7 +4714,6 @@ public class NotificationPanelViewController extends PanelViewController {
        CommunalSource existingSource = mCommunalSource != null ? mCommunalSource.get() : null;

        if (existingSource != null) {
            existingSource.removeCallback(mCommunalSourceCallback);
            mCommunalViewController.show(null /*source*/);
        }

@@ -4728,7 +4722,6 @@ public class NotificationPanelViewController extends PanelViewController {
        CommunalSource currentSource = mCommunalSource != null ? mCommunalSource.get() : null;
        // Set source and register callback
        if (currentSource != null && mCommunalViewController != null) {
            currentSource.addCallback(mCommunalSourceCallback);
            mCommunalViewController.show(source);
        }

+7 −5
Original line number Diff line number Diff line
@@ -16,9 +16,7 @@

package com.android.systemui.util.service;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -26,6 +24,8 @@ import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;

import com.android.systemui.dagger.qualifiers.Main;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -35,6 +35,8 @@ import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

import javax.inject.Inject;

/**
 * {@link ObservableServiceConnection} is a concrete implementation of {@link ServiceConnection}
 * that enables monitoring the status of a binder connection. It also aides in automatically
@@ -119,17 +121,17 @@ public class ObservableServiceConnection<T> implements ServiceConnection {
     * Default constructor for {@link ObservableServiceConnection}.
     * @param context The context from which the service will be bound with.
     * @param serviceIntent The intent to  bind service with.
     * @param flags The flags to use during the binding
     * @param executor The executor for connection callbacks to be delivered on
     * @param transformer A {@link ServiceTransformer} for transforming the resulting service
     *                    into a desired type.
     */
    @Inject
    public ObservableServiceConnection(Context context, Intent serviceIntent,
            @Context.BindServiceFlags int flags, @NonNull @CallbackExecutor Executor executor,
            @Main Executor executor,
            ServiceTransformer<T> transformer) {
        mContext = context;
        mServiceIntent = serviceIntent;
        mFlags = flags;
        mFlags = Context.BIND_AUTO_CREATE;
        mExecutor = executor;
        mTransformer = transformer;
        mCallbacks = new ArrayList<>();
Loading