Skip to content
Snippets Groups Projects
Commit a3decbe1 authored by Patrick Williams's avatar Patrick Williams Committed by Android (Google) Code Review
Browse files

Merge "Add WindowInfosListenerForTest" into udc-dev

parents bc890bb1 f810101b
No related branches found
No related tags found
No related merge requests found
......@@ -3939,6 +3939,18 @@ package android.window {
method public abstract void onTransactionReady(int, @NonNull android.view.SurfaceControl.Transaction);
}
public class WindowInfosListenerForTest {
ctor public WindowInfosListenerForTest();
method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public void addWindowInfosListener(@NonNull java.util.function.Consumer<java.util.List<android.window.WindowInfosListenerForTest.WindowInfo>>);
method public void removeWindowInfosListener(@NonNull java.util.function.Consumer<java.util.List<android.window.WindowInfosListenerForTest.WindowInfo>>);
}
public static class WindowInfosListenerForTest.WindowInfo {
field @NonNull public final android.graphics.Rect bounds;
field @NonNull public final String name;
field @NonNull public final android.os.IBinder windowToken;
}
public class WindowOrganizer {
ctor public WindowOrganizer();
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
......
......@@ -244,6 +244,10 @@ public final class InputWindowHandle {
window = iwindow;
}
public @Nullable IBinder getWindowToken() {
return windowToken;
}
public IWindow getWindow() {
if (window != null) {
return window;
......
......@@ -16,6 +16,8 @@
package android.window;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.graphics.Matrix;
import android.util.Pair;
import android.util.Size;
......@@ -49,10 +51,13 @@ public abstract class WindowInfosListener {
/**
* Register the WindowInfosListener.
*
* Registering WindowInfosListeners should only be done within system_server and shell.
*
* @return The cached values for InputWindowHandles and DisplayInfos. This is the last updated
* value that was sent from SurfaceFlinger to this particular process. If there was nothing
* registered previously, then the data can be empty.
*/
@RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
public Pair<InputWindowHandle[], DisplayInfo[]> register() {
return nativeRegister(mNativeListener);
}
......@@ -65,8 +70,12 @@ public abstract class WindowInfosListener {
}
private static native long nativeCreate(WindowInfosListener thiz);
@RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
private static native Pair<InputWindowHandle[], DisplayInfo[]> nativeRegister(long ptr);
private static native void nativeUnregister(long ptr);
private static native long nativeGetFinalizer();
/**
......
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.InputConfig;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;
import android.view.InputWindowHandle;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
/**
* Wrapper class to provide access to WindowInfosListener within tests.
*
* @hide
*/
@TestApi
public class WindowInfosListenerForTest {
/**
* Window properties passed to {@code @WindowInfosListenerForTest#onWindowInfosChanged}.
*/
public static class WindowInfo {
/**
* The window's token.
*/
@NonNull
public final IBinder windowToken;
/**
* The window's name.
*/
@NonNull
public final String name;
/**
* The window's position and size in display space.
*/
@NonNull
public final Rect bounds;
WindowInfo(@NonNull IBinder windowToken, @NonNull String name, @NonNull Rect bounds) {
this.windowToken = windowToken;
this.name = name;
this.bounds = bounds;
}
}
private static final String TAG = "WindowInfosListenerForTest";
private ArrayMap<Consumer<List<WindowInfo>>, WindowInfosListener> mListeners;
public WindowInfosListenerForTest() {
mListeners = new ArrayMap<>();
}
/**
* Register a listener that is called when the system's list of visible windows has changes in
* position or visibility.
*
* @param consumer Consumer that is called with reverse Z ordered lists of WindowInfo instances
* where the first value is the topmost window.
*/
@RequiresPermission(Manifest.permission.ACCESS_SURFACE_FLINGER)
public void addWindowInfosListener(
@NonNull Consumer<List<WindowInfo>> consumer) {
var calledWithInitialState = new CountDownLatch(1);
var listener = new WindowInfosListener() {
@Override
public void onWindowInfosChanged(InputWindowHandle[] windowHandles,
DisplayInfo[] displayInfos) {
try {
calledWithInitialState.await();
} catch (InterruptedException exception) {
Log.e(TAG,
"Exception thrown while waiting for listener to be called with "
+ "initial state");
}
consumer.accept(buildWindowInfos(windowHandles));
}
};
mListeners.put(consumer, listener);
Pair<InputWindowHandle[], WindowInfosListener.DisplayInfo[]> initialState =
listener.register();
consumer.accept(buildWindowInfos(initialState.first));
calledWithInitialState.countDown();
}
/**
* Unregisters the listener.
*/
public void removeWindowInfosListener(@NonNull Consumer<List<WindowInfo>> consumer) {
WindowInfosListener listener = mListeners.remove(consumer);
if (listener == null) {
return;
}
listener.unregister();
}
private static List<WindowInfo> buildWindowInfos(InputWindowHandle[] windowHandles) {
var windowInfos = new ArrayList<WindowInfo>(windowHandles.length);
for (var handle : windowHandles) {
if ((handle.inputConfig & InputConfig.NOT_VISIBLE) != 0) {
continue;
}
var bounds = new Rect(handle.frameLeft, handle.frameTop, handle.frameRight,
handle.frameBottom);
windowInfos.add(new WindowInfo(handle.getWindowToken(), handle.name, bounds));
}
return windowInfos;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment