4/ Update HideDisplayCutout and AppPairs to use shell main thread

Bug: 161979899
Test: atest WMShellUnitTests
Change-Id: I369e83cbc85fea80b0db4d58ba8d05d12fbd09e3
This commit is contained in:
Winson Chung
2020-12-07 22:54:02 -08:00
parent 5b43185172
commit 813664c88c
4 changed files with 114 additions and 25 deletions

View File

@@ -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");
}
}
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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);
}

View File

@@ -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