Notify when task changes requested orientation.
This allows listener know task's orientation request change before handling display rotation through IDisplayWindowRotationController if they can register a local TaskStackListener. Bug: 150409355 Test: atest WmTests:TaskStackChangedListenerTest#testNotifyTaskRequestedOrientationChanged Change-Id: Id7bfc3e63329ce26d454b7e9c143e084e04dd365
This commit is contained in:
@@ -205,4 +205,15 @@ oneway interface ITaskStackListener {
|
||||
* @param {@code true} if the task got focus, {@code false} if it lost it.
|
||||
*/
|
||||
void onTaskFocusChanged(int taskId, boolean focused);
|
||||
|
||||
/**
|
||||
* Called when a task changes its requested orientation. It is different from {@link
|
||||
* #onActivityRequestedOrientationChanged(int, int)} in the sense that this method is called
|
||||
* when a task changes requested orientation due to activity launch, dimiss or reparenting.
|
||||
*
|
||||
* @param taskId id of the task.
|
||||
* @param requestedOrientation the new requested orientation of this task as screen orientations
|
||||
* in {@link android.content.pm.ActivityInfo}.
|
||||
*/
|
||||
void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation);
|
||||
}
|
||||
|
||||
@@ -195,4 +195,8 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub {
|
||||
@Override
|
||||
public void onTaskFocusChanged(int taskId, boolean focused) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1392,6 +1392,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
final WindowContainer orientationSource = getLastOrientationSource();
|
||||
final ActivityRecord r =
|
||||
orientationSource != null ? orientationSource.asActivityRecord() : null;
|
||||
if (r != null && r.getTask() != null
|
||||
&& orientation != r.getTask().mLastReportedRequestedOrientation) {
|
||||
final Task task = r.getTask();
|
||||
task.mLastReportedRequestedOrientation = orientation;
|
||||
mAtmService.getTaskChangeNotificationController()
|
||||
.notifyTaskRequestedOrientationChanged(task.mTaskId, orientation);
|
||||
}
|
||||
// Currently there is no use case from non-activity.
|
||||
if (r != null && handleTopActivityLaunchingInDifferentOrientation(r)) {
|
||||
// Display orientation should be deferred until the top fixed rotation is finished.
|
||||
|
||||
@@ -368,6 +368,14 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
@Surface.Rotation
|
||||
private int mRotation;
|
||||
|
||||
/**
|
||||
* Last requested orientation reported to DisplayContent. This is different from {@link
|
||||
* #mOrientation} in the sense that this takes activities' requested orientation into
|
||||
* account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
|
||||
* to notify for activities that don't specify any orientation.
|
||||
*/
|
||||
int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
|
||||
// For comparison with DisplayContent bounds.
|
||||
private Rect mTmpRect = new Rect();
|
||||
// For handling display rotations.
|
||||
|
||||
@@ -60,6 +60,7 @@ class TaskChangeNotificationController {
|
||||
private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
|
||||
private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
|
||||
private static final int NOTIFY_TASK_FOCUS_CHANGED_MSG = 27;
|
||||
private static final int NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG = 28;
|
||||
|
||||
// Delay in notifying task stack change listeners (in millis)
|
||||
private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
|
||||
@@ -178,6 +179,10 @@ class TaskChangeNotificationController {
|
||||
l.onTaskFocusChanged(m.arg1, m.arg2 != 0);
|
||||
};
|
||||
|
||||
private final TaskStackConsumer mNotifyTaskRequestedOrientationChanged = (l, m) -> {
|
||||
l.onTaskRequestedOrientationChanged(m.arg1, m.arg2);
|
||||
};
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TaskStackConsumer {
|
||||
void accept(ITaskStackListener t, Message m) throws RemoteException;
|
||||
@@ -269,6 +274,9 @@ class TaskChangeNotificationController {
|
||||
case NOTIFY_TASK_FOCUS_CHANGED_MSG:
|
||||
forAllRemoteListeners(mNotifyTaskFocusChanged, msg);
|
||||
break;
|
||||
case NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG:
|
||||
forAllRemoteListeners(mNotifyTaskRequestedOrientationChanged, msg);
|
||||
break;
|
||||
}
|
||||
if (msg.obj instanceof SomeArgs) {
|
||||
((SomeArgs) msg.obj).recycle();
|
||||
@@ -558,4 +566,12 @@ class TaskChangeNotificationController {
|
||||
forAllLocalListeners(mNotifyTaskFocusChanged, msg);
|
||||
msg.sendToTarget();
|
||||
}
|
||||
|
||||
/** @see android.app.ITaskStackListener#onTaskRequestedOrientationChanged(int, int) */
|
||||
void notifyTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
|
||||
final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REQUESTED_ORIENTATION_CHANGED_MSG,
|
||||
taskId, requestedOrientation);
|
||||
forAllLocalListeners(mNotifyTaskRequestedOrientationChanged, msg);
|
||||
msg.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@
|
||||
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityViewTestActivity" />
|
||||
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityInActivityView"
|
||||
android:resizeableActivity="true" />
|
||||
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$LandscapeActivity"
|
||||
android:screenOrientation="sensorLandscape"
|
||||
android:showWhenLocked="true"
|
||||
android:turnScreenOn="true" />
|
||||
<activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity"
|
||||
android:showWhenLocked="true" />
|
||||
</application>
|
||||
|
||||
@@ -22,6 +22,7 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.Activity;
|
||||
@@ -41,6 +42,7 @@ import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.text.TextUtils;
|
||||
@@ -56,8 +58,10 @@ import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Build/Install/Run:
|
||||
@@ -391,6 +395,42 @@ public class TaskStackChangedListenerTest {
|
||||
}
|
||||
};
|
||||
|
||||
@Presubmit
|
||||
@FlakyTest(bugId = 150409355)
|
||||
@Test
|
||||
public void testNotifyTaskRequestedOrientationChanged() throws Exception {
|
||||
final ArrayBlockingQueue<int[]> taskIdAndOrientationQueue = new ArrayBlockingQueue<>(10);
|
||||
registerTaskStackChangedListener(new TaskStackListener() {
|
||||
@Override
|
||||
public void onTaskRequestedOrientationChanged(int taskId, int requestedOrientation) {
|
||||
int[] taskIdAndOrientation = new int[2];
|
||||
taskIdAndOrientation[0] = taskId;
|
||||
taskIdAndOrientation[1] = requestedOrientation;
|
||||
taskIdAndOrientationQueue.offer(taskIdAndOrientation);
|
||||
}
|
||||
});
|
||||
|
||||
final LandscapeActivity activity =
|
||||
(LandscapeActivity) startTestActivity(LandscapeActivity.class);
|
||||
|
||||
int[] taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
|
||||
candidate -> candidate[0] == activity.getTaskId());
|
||||
assertNotNull(taskIdAndOrientation);
|
||||
assertEquals(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE, taskIdAndOrientation[1]);
|
||||
|
||||
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
|
||||
taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
|
||||
candidate -> candidate[0] == activity.getTaskId());
|
||||
assertNotNull(taskIdAndOrientation);
|
||||
assertEquals(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT, taskIdAndOrientation[1]);
|
||||
|
||||
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
taskIdAndOrientation = waitForResult(taskIdAndOrientationQueue,
|
||||
candidate -> candidate[0] == activity.getTaskId());
|
||||
assertNotNull(taskIdAndOrientation);
|
||||
assertEquals(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, taskIdAndOrientation[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the provided activity and returns the started instance.
|
||||
*/
|
||||
@@ -432,6 +472,19 @@ public class TaskStackChangedListenerTest {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T waitForResult(ArrayBlockingQueue<T> queue, Predicate<T> predicate) {
|
||||
try {
|
||||
final long timeout = SystemClock.uptimeMillis() + TimeUnit.SECONDS.toMillis(15);
|
||||
T result;
|
||||
do {
|
||||
result = queue.poll(timeout - SystemClock.uptimeMillis(), TimeUnit.MILLISECONDS);
|
||||
} while (result != null && !predicate.test(result));
|
||||
return result;
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestActivity extends Activity {
|
||||
boolean mIsResumed = false;
|
||||
|
||||
@@ -563,4 +616,6 @@ public class TaskStackChangedListenerTest {
|
||||
|
||||
// Activity that has {@link android.R.attr#resizeableActivity} attribute set to {@code true}
|
||||
public static class ActivityInActivityView extends TestActivity {}
|
||||
|
||||
public static class LandscapeActivity extends TestActivity {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user