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

Commit 813664c8 authored by Winson Chung's avatar Winson Chung
Browse files

4/ Update HideDisplayCutout and AppPairs to use shell main thread

Bug: 161979899
Test: atest WMShellUnitTests
Change-Id: I369e83cbc85fea80b0db4d58ba8d05d12fbd09e3
parent 5b431851
Loading
Loading
Loading
Loading
+77 −13
Original line number Diff line number Diff line
@@ -19,41 +19,58 @@ package com.android.wm.shell.apppairs;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;

import android.app.ActivityManager;
import android.util.Slog;
import android.util.SparseArray;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
 */
public class AppPairsController implements AppPairs {
public class AppPairsController {
    private static final String TAG = AppPairsController.class.getSimpleName();

    private final ShellTaskOrganizer mTaskOrganizer;
    private final SyncTransactionQueue mSyncQueue;
    private final ShellExecutor mMainExecutor;
    private final AppPairsImpl mImpl = new AppPairsImpl();

    private AppPairsPool mPairsPool;
    // Active app-pairs mapped by root task id key.
    private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
    private final DisplayController mDisplayController;

    public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
                DisplayController displayController) {
    /**
     * Creates {@link AppPairs}, returns {@code null} if the feature is not supported.
     */
    @Nullable
    public static AppPairs create(ShellTaskOrganizer organizer,
            SyncTransactionQueue syncQueue, DisplayController displayController,
            ShellExecutor mainExecutor) {
        return new AppPairsController(organizer, syncQueue, displayController,
                mainExecutor).mImpl;
    }

    AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
                DisplayController displayController, ShellExecutor mainExecutor) {
        mTaskOrganizer = organizer;
        mSyncQueue = syncQueue;
        mDisplayController = displayController;
        mMainExecutor = mainExecutor;
    }

    @Override
    public void onOrganizerRegistered() {
    void onOrganizerRegistered() {
        if (mPairsPool == null) {
            setPairsPool(new AppPairsPool(this));
        }
@@ -64,8 +81,7 @@ public class AppPairsController implements AppPairs {
        mPairsPool = pool;
    }

    @Override
    public boolean pair(int taskId1, int taskId2) {
    boolean pair(int taskId1, int taskId2) {
        final ActivityManager.RunningTaskInfo task1 = mTaskOrganizer.getRunningTaskInfo(taskId1);
        final ActivityManager.RunningTaskInfo task2 = mTaskOrganizer.getRunningTaskInfo(taskId2);
        if (task1 == null || task2 == null) {
@@ -74,8 +90,7 @@ public class AppPairsController implements AppPairs {
        return pair(task1, task2);
    }

    @Override
    public boolean pair(ActivityManager.RunningTaskInfo task1,
    boolean pair(ActivityManager.RunningTaskInfo task1,
            ActivityManager.RunningTaskInfo task2) {
        return pairInner(task1, task2) != null;
    }
@@ -94,8 +109,7 @@ public class AppPairsController implements AppPairs {
        return pair;
    }

    @Override
    public void unpair(int taskId) {
    void unpair(int taskId) {
        unpair(taskId, true /* releaseToPool */);
    }

@@ -135,8 +149,7 @@ public class AppPairsController implements AppPairs {
        return mDisplayController;
    }

    @Override
    public void dump(@NonNull PrintWriter pw, String prefix) {
    private void dump(@NonNull PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        final String childPrefix = innerPrefix + "  ";
        pw.println(prefix + this);
@@ -155,4 +168,55 @@ public class AppPairsController implements AppPairs {
        return TAG + "#" + mActiveAppPairs.size();
    }

    private class AppPairsImpl implements AppPairs {
        @Override
        public boolean pair(int task1, int task2) {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = AppPairsController.this.pair(task1, task2);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
            }
            return result[0];
        }

        @Override
        public boolean pair(ActivityManager.RunningTaskInfo task1,
                ActivityManager.RunningTaskInfo task2) {
            boolean[] result = new boolean[1];
            try {
                mMainExecutor.executeBlocking(() -> {
                    result[0] = AppPairsController.this.pair(task1, task2);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
            }
            return result[0];
        }

        @Override
        public void unpair(int taskId) {
            mMainExecutor.execute(() -> {
                AppPairsController.this.unpair(taskId);
            });
        }

        @Override
        public void onOrganizerRegistered() {
            mMainExecutor.execute(() -> {
                AppPairsController.this.onOrganizerRegistered();
            });
        }

        @Override
        public void dump(@NonNull PrintWriter pw, String prefix) {
            try {
                mMainExecutor.executeBlocking(() -> AppPairsController.this.dump(pw, prefix));
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump AppPairsController in 2s");
            }
        }
    }
}
+26 −8
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.wm.shell.hidedisplaycutout;
import android.content.Context;
import android.content.res.Configuration;
import android.os.SystemProperties;
import android.util.Slog;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -28,17 +29,18 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;

import java.io.PrintWriter;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * Manages the hide display cutout status.
 */
public class HideDisplayCutoutController implements HideDisplayCutout {
public class HideDisplayCutoutController {
    private static final String TAG = "HideDisplayCutoutController";

    private final Context mContext;
    private final HideDisplayCutoutOrganizer mOrganizer;
    private final ShellExecutor mMainExecutor;
    private final HideDisplayCutoutImpl mImpl = new HideDisplayCutoutImpl();
    @VisibleForTesting
    boolean mEnabled;

@@ -55,7 +57,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
     * supported.
     */
    @Nullable
    public static HideDisplayCutoutController create(
    public static HideDisplayCutout create(
            Context context, DisplayController displayController, ShellExecutor mainExecutor) {
        // The SystemProperty is set for devices that support this feature and is used to control
        // whether to create the HideDisplayCutout instance.
@@ -66,7 +68,7 @@ public class HideDisplayCutoutController implements HideDisplayCutout {

        HideDisplayCutoutOrganizer organizer =
                new HideDisplayCutoutOrganizer(context, displayController, mainExecutor);
        return new HideDisplayCutoutController(context, organizer, mainExecutor);
        return new HideDisplayCutoutController(context, organizer, mainExecutor).mImpl;
    }

    @VisibleForTesting
@@ -88,13 +90,11 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
    private void onConfigurationChanged(Configuration newConfig) {
        updateStatus();
    }

    @Override
    public void dump(@NonNull PrintWriter pw) {
    private void dump(@NonNull PrintWriter pw) {
        final String prefix = "  ";
        pw.print(TAG);
        pw.println(" states: ");
@@ -103,4 +103,22 @@ public class HideDisplayCutoutController implements HideDisplayCutout {
        pw.println(mEnabled);
        mOrganizer.dump(pw);
    }

    private class HideDisplayCutoutImpl implements HideDisplayCutout {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            mMainExecutor.execute(() -> {
                HideDisplayCutoutController.this.onConfigurationChanged(newConfig);
            });
        }

        @Override
        public void dump(@NonNull PrintWriter pw) {
            try {
                mMainExecutor.executeBlocking(() -> HideDisplayCutoutController.this.dump(pw));
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump HideDisplayCutoutController in 2s");
            }
        }
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -16,16 +16,21 @@

package com.android.wm.shell.apppairs;

import static org.mockito.Mockito.mock;

import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;

import org.mockito.Mock;

public class TestAppPairsController extends AppPairsController {
    TestAppPairsPool mPool;
    private TestAppPairsPool mPool;

    public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
            DisplayController displayController) {
        super(organizer, syncQueue, displayController);
        super(organizer, syncQueue, displayController, mock(ShellExecutor.class));
        mPool = new TestAppPairsPool(this);
        setPairsPool(mPool);
    }
+4 −2
Original line number Diff line number Diff line
@@ -84,8 +84,10 @@ public class WMShellModule {
    @WMSingleton
    @Provides
    static AppPairs provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue, DisplayController displayController) {
        return new AppPairsController(shellTaskOrganizer, syncQueue, displayController);
            SyncTransactionQueue syncQueue, DisplayController displayController,
            @ShellMainThread ShellExecutor mainExecutor) {
        return AppPairsController.create(shellTaskOrganizer, syncQueue, displayController,
                mainExecutor);
    }

    @WMSingleton