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

Commit 4380b2c2 authored by Rasheed Lewis's avatar Rasheed Lewis Committed by Android (Google) Code Review
Browse files

Merge "Move TileLifecycleManager calls to background thread" into udc-dev

parents b98c2ee5 b3fcc618
Loading
Loading
Loading
Loading
+47 −38
Original line number Diff line number Diff line
@@ -42,7 +42,9 @@ import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;

import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.util.concurrency.DelayableExecutor;

import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
@@ -88,6 +90,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements
    private final Handler mHandler;
    private final Intent mIntent;
    private final UserHandle mUser;
    private final DelayableExecutor mExecutor;
    private final IBinder mToken = new Binder();
    private final PackageManagerAdapter mPackageManagerAdapter;
    private final BroadcastDispatcher mBroadcastDispatcher;
@@ -100,25 +103,27 @@ public class TileLifecycleManager extends BroadcastReceiver implements

    private int mBindTryCount;
    private int mBindRetryDelay = DEFAULT_BIND_RETRY_DELAY;
    private boolean mBound;
    private AtomicBoolean mBound = new AtomicBoolean(false);
    private AtomicBoolean mPackageReceiverRegistered = new AtomicBoolean(false);
    private AtomicBoolean mUserReceiverRegistered = new AtomicBoolean(false);
    private boolean mUnbindImmediate;
    private AtomicBoolean mUnbindImmediate = new AtomicBoolean(false);
    @Nullable
    private TileChangeListener mChangeListener;
    // Return value from bindServiceAsUser, determines whether safe to call unbind.
    private boolean mIsBound;
    private AtomicBoolean mIsBound = new AtomicBoolean(false);

    @AssistedInject
    TileLifecycleManager(@Main Handler handler, Context context, IQSService service,
            PackageManagerAdapter packageManagerAdapter, BroadcastDispatcher broadcastDispatcher,
            @Assisted Intent intent, @Assisted UserHandle user) {
            @Assisted Intent intent, @Assisted UserHandle user,
            @Background DelayableExecutor executor) {
        mContext = context;
        mHandler = handler;
        mIntent = intent;
        mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
        mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
        mUser = user;
        mExecutor = executor;
        mPackageManagerAdapter = packageManagerAdapter;
        mBroadcastDispatcher = broadcastDispatcher;
        if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
@@ -184,22 +189,21 @@ public class TileLifecycleManager extends BroadcastReceiver implements
     * Binds just long enough to send any queued messages, then unbinds.
     */
    public void flushMessagesAndUnbind() {
        mUnbindImmediate = true;
        mExecutor.execute(() -> {
            mUnbindImmediate.set(true);
            setBindService(true);
        });
    }

    /**
     * Binds or unbinds to IQSService
     */
    @WorkerThread
    public void setBindService(boolean bind) {
        if (mBound && mUnbindImmediate) {
    private void setBindService(boolean bind) {
        if (mBound.get() && mUnbindImmediate.get()) {
            // If we are already bound and expecting to unbind, this means we should stay bound
            // because something else wants to hold the connection open.
            mUnbindImmediate = false;
            mUnbindImmediate.set(false);
            return;
        }
        mBound = bind;
        mBound.set(bind);
        if (bind) {
            if (mBindTryCount == MAX_BIND_RETRIES) {
                // Too many failures, give up on this tile until an update.
@@ -212,31 +216,38 @@ public class TileLifecycleManager extends BroadcastReceiver implements
            if (DEBUG) Log.d(TAG, "Binding service " + mIntent + " " + mUser);
            mBindTryCount++;
            try {
                mIsBound = bindServices();
                if (!mIsBound) {
                mIsBound.set(bindServices());
                if (!mIsBound.get()) {
                    mContext.unbindService(this);
                }
            } catch (SecurityException e) {
                Log.e(TAG, "Failed to bind to service", e);
                mIsBound = false;
                mIsBound.set(false);
            }
        } else {
            if (DEBUG) Log.d(TAG, "Unbinding service " + mIntent + " " + mUser);
            // Give it another chance next time it needs to be bound, out of kindness.
            mBindTryCount = 0;
            freeWrapper();
            if (mIsBound) {
            if (mIsBound.get()) {
                try {
                    mContext.unbindService(this);
                } catch (Exception e) {
                    Log.e(TAG, "Failed to unbind service "
                            + mIntent.getComponent().flattenToShortString(), e);
                }
                mIsBound = false;
                mIsBound.set(false);
            }
        }
    }

    /**
     * Binds or unbinds to IQSService
     */
    public void executeSetBindService(boolean bind) {
        mExecutor.execute(() -> setBindService(bind));
    }

    private boolean bindServices() {
        String packageName = mIntent.getComponent().getPackageName();
        if (CompatChanges.isChangeEnabled(START_ACTIVITY_NEEDS_PENDING_INTENT, packageName,
@@ -317,10 +328,12 @@ public class TileLifecycleManager extends BroadcastReceiver implements
            }
            onTileRemoved();
        }
        if (mUnbindImmediate) {
            mUnbindImmediate = false;
        mExecutor.execute(() -> {
            if (mUnbindImmediate.get()) {
                mUnbindImmediate.set(false);
                setBindService(false);
            }
        });
    }

    public void handleDestroy() {
@@ -335,19 +348,11 @@ public class TileLifecycleManager extends BroadcastReceiver implements
        if (mWrapper == null) return;
        freeWrapper();
        // Clearly not bound anymore
        mIsBound = false;
        if (!mBound) return;
        mIsBound.set(false);
        if (!mBound.get()) return;
        if (DEBUG) Log.d(TAG, "handleDeath");
        if (checkComponentState()) {
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (mBound) {
                        // Retry binding.
                        setBindService(true);
                    }
                }
            }, mBindRetryDelay);
            mExecutor.executeDelayed(() -> setBindService(true), mBindRetryDelay);
        }
    }

@@ -410,11 +415,15 @@ public class TileLifecycleManager extends BroadcastReceiver implements
            mChangeListener.onTileChanged(mIntent.getComponent());
        }
        stopPackageListening();
        if (mBound) {
            // Trying to bind again will check the state of the package before bothering to bind.
        mExecutor.execute(() -> {
            if (mBound.get()) {
                // Trying to bind again will check the state of the package before bothering to
                // bind.
                if (DEBUG) Log.d(TAG, "Trying to rebind");
                setBindService(true);
            }

        });
    }

    private boolean isComponentAvailable() {
+7 −6
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.util.concurrency.DelayableExecutor;

import java.util.List;
import java.util.Objects;
@@ -75,12 +76,12 @@ public class TileServiceManager {

    TileServiceManager(TileServices tileServices, Handler handler, ComponentName component,
            BroadcastDispatcher broadcastDispatcher, UserTracker userTracker,
            CustomTileAddedRepository customTileAddedRepository) {
            CustomTileAddedRepository customTileAddedRepository, DelayableExecutor executor) {
        this(tileServices, handler, userTracker, customTileAddedRepository,
                new TileLifecycleManager(handler, tileServices.getContext(), tileServices,
                        new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
                        new Intent(TileService.ACTION_QS_TILE).setComponent(component),
                userTracker.getUserHandle()));
                        userTracker.getUserHandle(), executor));
    }

    @VisibleForTesting
@@ -203,7 +204,7 @@ public class TileServiceManager {
        mBound = true;
        mJustBound = true;
        mHandler.postDelayed(mJustBoundOver, MIN_BIND_TIME);
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
    }

    private void unbindService() {
@@ -213,7 +214,7 @@ public class TileServiceManager {
        }
        mBound = false;
        mJustBound = false;
        mStateManager.setBindService(false);
        mStateManager.executeSetBindService(false);
    }

    public void calculateBindPriority(long currentTime) {
+7 −2
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository;
@@ -47,6 +48,7 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.DelayableExecutor;

import java.util.ArrayList;
import java.util.Collections;
@@ -79,6 +81,7 @@ public class TileServices extends IQSService.Stub {
    private final StatusBarIconController mStatusBarIconController;
    private final PanelInteractor mPanelInteractor;
    private final CustomTileAddedRepository mCustomTileAddedRepository;
    private final DelayableExecutor mBackgroundExecutor;

    private int mMaxBound = DEFAULT_MAX_BOUND;

@@ -92,7 +95,8 @@ public class TileServices extends IQSService.Stub {
            CommandQueue commandQueue,
            StatusBarIconController statusBarIconController,
            PanelInteractor panelInteractor,
            CustomTileAddedRepository customTileAddedRepository) {
            CustomTileAddedRepository customTileAddedRepository,
            @Background DelayableExecutor backgroundExecutor) {
        mHost = host;
        mKeyguardStateController = keyguardStateController;
        mContext = mHost.getContext();
@@ -105,6 +109,7 @@ public class TileServices extends IQSService.Stub {
        mCommandQueue.addCallback(mRequestListeningCallback);
        mPanelInteractor = panelInteractor;
        mCustomTileAddedRepository = customTileAddedRepository;
        mBackgroundExecutor = backgroundExecutor;
    }

    public Context getContext() {
@@ -132,7 +137,7 @@ public class TileServices extends IQSService.Stub {
    protected TileServiceManager onCreateTileService(ComponentName component,
            BroadcastDispatcher broadcastDispatcher) {
        return new TileServiceManager(this, mHandlerProvider.get(), component,
                broadcastDispatcher, mUserTracker, mCustomTileAddedRepository);
                broadcastDispatcher, mUserTracker, mCustomTileAddedRepository, mBackgroundExecutor);
    }

    public void freeService(CustomTile tile, TileServiceManager service) {
+2 −1
Original line number Diff line number Diff line
@@ -145,7 +145,8 @@ public class QSTileHostTest extends SysuiTestCase {
        mMainExecutor = new FakeExecutor(new FakeSystemClock());

        mSharedPreferencesByUser = new SparseArray<>();
        when(mTileLifecycleManagerFactory.create(any(Intent.class), any(UserHandle.class)))
        when(mTileLifecycleManagerFactory
                .create(any(Intent.class), any(UserHandle.class)))
                .thenReturn(mTileLifecycleManager);
        when(mUserFileManager.getSharedPreferences(anyString(), anyInt(), anyInt()))
                .thenAnswer((Answer<SharedPreferences>) invocation -> {
+49 −24
Original line number Diff line number Diff line
@@ -60,6 +60,8 @@ import androidx.test.runner.AndroidJUnit4;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;

import org.junit.After;
import org.junit.Before;
@@ -81,6 +83,7 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
    private ComponentName mTileServiceComponentName;
    private Intent mTileServiceIntent;
    private UserHandle mUser;
    private FakeExecutor mExecutor;
    private HandlerThread mThread;
    private Handler mHandler;
    private TileLifecycleManager mStateManager;
@@ -109,12 +112,14 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
        mThread = new HandlerThread("TestThread");
        mThread.start();
        mHandler = Handler.createAsync(mThread.getLooper());
        mExecutor = new FakeExecutor(new FakeSystemClock());
        mStateManager = new TileLifecycleManager(mHandler, mWrappedContext,
                mock(IQSService.class),
                mMockPackageManagerAdapter,
                mMockBroadcastDispatcher,
                mTileServiceIntent,
                mUser);
                mUser,
                mExecutor);
    }

    @After
@@ -152,7 +157,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {

    @Test
    public void testBind() {
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        verifyBind(1);
    }

@@ -160,7 +166,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
    public void testPackageReceiverExported() throws Exception {
        // Make sure that we register a receiver
        setPackageEnabled(false);
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        IntentFilter filter = mWrappedContext.mLastIntentFilter;
        assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_ADDED));
        assertTrue(filter.hasAction(Intent.ACTION_PACKAGE_CHANGED));
@@ -170,14 +177,17 @@ public class TileLifecycleManagerTest extends SysuiTestCase {

    @Test
    public void testUnbind() {
        mStateManager.setBindService(true);
        mStateManager.setBindService(false);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        mStateManager.executeSetBindService(false);
        mExecutor.runAllReady();
        assertFalse(mContext.isBound(mTileServiceComponentName));
    }

    @Test
    public void testTileServiceCallbacks() throws Exception {
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        mStateManager.onTileAdded();
        verify(mMockTileService).onTileAdded();
        mStateManager.onStartListening();
@@ -193,7 +203,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
    @Test
    public void testAddedBeforeBind() throws Exception {
        mStateManager.onTileAdded();
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();

        verifyBind(1);
        verify(mMockTileService).onTileAdded();
@@ -203,7 +214,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
    public void testListeningBeforeBind() throws Exception {
        mStateManager.onTileAdded();
        mStateManager.onStartListening();
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();

        verifyBind(1);
        verify(mMockTileService).onTileAdded();
@@ -215,7 +227,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
        mStateManager.onTileAdded();
        mStateManager.onStartListening();
        mStateManager.onClick(null);
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();

        verifyBind(1);
        verify(mMockTileService).onTileAdded();
@@ -228,10 +241,12 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
        mStateManager.onTileAdded();
        mStateManager.onStartListening();
        mStateManager.onStopListening();
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();

        verifyBind(1);
        mStateManager.setBindService(false);
        mStateManager.executeSetBindService(false);
        mExecutor.runAllReady();
        assertFalse(mContext.isBound(mTileServiceComponentName));
        verify(mMockTileService, never()).onStartListening();
    }
@@ -242,10 +257,12 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
        mStateManager.onStartListening();
        mStateManager.onClick(null);
        mStateManager.onStopListening();
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();

        verifyBind(1);
        mStateManager.setBindService(false);
        mStateManager.executeSetBindService(false);
        mExecutor.runAllReady();
        assertFalse(mContext.isBound(mTileServiceComponentName));
        verify(mMockTileService, never()).onClick(null);
    }
@@ -255,7 +272,8 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
        mStateManager.onTileAdded();
        mStateManager.onStartListening();
        setPackageEnabled(false);
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        // Package not available, not yet created.
        verifyBind(0);

@@ -267,18 +285,19 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
                        Intent.ACTION_PACKAGE_CHANGED,
                        Uri.fromParts(
                                "package", mTileServiceComponentName.getPackageName(), null)));
        mExecutor.runAllReady();
        verifyBind(1);
    }

    @Test
    public void testKillProcess() throws Exception {
        mStateManager.onStartListening();
        mStateManager.setBindService(true);
        mStateManager.executeSetBindService(true);
        mExecutor.runAllReady();
        mStateManager.setBindRetryDelay(0);
        mExecutor.runAllReady();
        mStateManager.onServiceDisconnected(mTileServiceComponentName);

        // Guarantees mHandler has processed all messages.
        assertTrue(mHandler.runWithScissors(()->{}, TEST_FAIL_TIMEOUT));
        mExecutor.runAllReady();

        // Two calls: one for the first bind, one for the restart.
        verifyBind(2);
@@ -299,9 +318,11 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
                mMockPackageManagerAdapter,
                mMockBroadcastDispatcher,
                mTileServiceIntent,
                mUser);
                mUser,
                mExecutor);

        manager.setBindService(true);
        manager.executeSetBindService(true);
        mExecutor.runAllReady();

        ArgumentCaptor<ServiceConnection> captor = ArgumentCaptor.forClass(ServiceConnection.class);
        verify(falseContext).bindServiceAsUser(any(), captor.capture(), anyInt(), any());
@@ -318,9 +339,11 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
                mMockPackageManagerAdapter,
                mMockBroadcastDispatcher,
                mTileServiceIntent,
                mUser);
                mUser,
                mExecutor);

        manager.setBindService(true);
        manager.executeSetBindService(true);
        mExecutor.runAllReady();
        int flags = Context.BIND_AUTO_CREATE
                | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
                | Context.BIND_WAIVE_PRIORITY;
@@ -337,9 +360,11 @@ public class TileLifecycleManagerTest extends SysuiTestCase {
                mMockPackageManagerAdapter,
                mMockBroadcastDispatcher,
                mTileServiceIntent,
                mUser);
                mUser,
                mExecutor);

        manager.setBindService(true);
        manager.executeSetBindService(true);
        mExecutor.runAllReady();
        int flags = Context.BIND_AUTO_CREATE
                | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE
                | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS
Loading