Merge "Exposing flickerlib classes and layer tracing to sysui"
am: e25075b2fb
Change-Id: I182eef2c7f93d68bcdceaec3fcdfaf9615eda0ea
This commit is contained in:
@@ -638,4 +638,14 @@ interface IWindowManager
|
|||||||
* native InputManager before proceeding with tests.
|
* native InputManager before proceeding with tests.
|
||||||
*/
|
*/
|
||||||
void syncInputTransactions();
|
void syncInputTransactions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether SurfaceFlinger layer tracing is enabled.
|
||||||
|
*/
|
||||||
|
boolean isLayerTracing();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables/disables SurfaceFlinger layer tracing.
|
||||||
|
*/
|
||||||
|
void setLayerTracing(boolean enabled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7806,4 +7806,64 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
|
0 /* configChanges */, !PRESERVE_WINDOWS, true /* notifyClients */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return whether layer tracing is enabled */
|
||||||
|
public boolean isLayerTracing() {
|
||||||
|
mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.DUMP,
|
||||||
|
"isLayerTracing");
|
||||||
|
long token = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
Parcel data = null;
|
||||||
|
Parcel reply = null;
|
||||||
|
try {
|
||||||
|
IBinder sf = ServiceManager.getService("SurfaceFlinger");
|
||||||
|
if (sf != null) {
|
||||||
|
reply = Parcel.obtain();
|
||||||
|
data = Parcel.obtain();
|
||||||
|
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
||||||
|
sf.transact(/* LAYER_TRACE_STATUS_CODE */ 1026, data, reply, 0 /* flags */);
|
||||||
|
return reply.readBoolean();
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to get layer tracing");
|
||||||
|
} finally {
|
||||||
|
if (data != null) {
|
||||||
|
data.recycle();
|
||||||
|
}
|
||||||
|
if (reply != null) {
|
||||||
|
reply.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Enable or disable layer tracing */
|
||||||
|
public void setLayerTracing(boolean enabled) {
|
||||||
|
mAtmInternal.enforceCallerIsRecentsOrHasPermission(android.Manifest.permission.DUMP,
|
||||||
|
"setLayerTracing");
|
||||||
|
long token = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
Parcel data = null;
|
||||||
|
try {
|
||||||
|
IBinder sf = ServiceManager.getService("SurfaceFlinger");
|
||||||
|
if (sf != null) {
|
||||||
|
data = Parcel.obtain();
|
||||||
|
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
||||||
|
data.writeInt(enabled ? 1 : 0);
|
||||||
|
sf.transact(/* LAYER_TRACE_CONTROL_CODE */ 1025, data, null, 0 /* flags */);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to set layer tracing");
|
||||||
|
} finally {
|
||||||
|
if (data != null) {
|
||||||
|
data.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,24 @@ java_test {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "flickerlib_without_helpers",
|
||||||
|
platform_apis: true,
|
||||||
|
srcs: ["src/**/*.java"],
|
||||||
|
exclude_srcs: ["src/**/helpers/*.java"],
|
||||||
|
static_libs: [
|
||||||
|
"cts-wm-util",
|
||||||
|
"platformprotosnano",
|
||||||
|
"layersprotosnano",
|
||||||
|
"truth-prebuilt"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "flickerautomationhelperlib",
|
name: "flickerautomationhelperlib",
|
||||||
sdk_version: "test_current",
|
sdk_version: "test_current",
|
||||||
srcs: [
|
srcs: [
|
||||||
"src/com/android/server/wm/flicker/AutomationUtils.java",
|
"src/com/android/server/wm/flicker/helpers/AutomationUtils.java",
|
||||||
"src/com/android/server/wm/flicker/WindowUtils.java",
|
"src/com/android/server/wm/flicker/WindowUtils.java",
|
||||||
],
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ import java.util.function.Function;
|
|||||||
* results. Assertions are functions that are applied over a single trace entry and returns a
|
* results. Assertions are functions that are applied over a single trace entry and returns a
|
||||||
* result which includes a detailed reason if the assertion fails.
|
* result which includes a detailed reason if the assertion fails.
|
||||||
*/
|
*/
|
||||||
class Assertions {
|
public class Assertions {
|
||||||
/**
|
/**
|
||||||
* Checks assertion on a single trace entry.
|
* Checks assertion on a single trace entry.
|
||||||
*
|
*
|
||||||
* @param <T> trace entry type to perform the assertion on.
|
* @param <T> trace entry type to perform the assertion on.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface TraceAssertion<T> extends Function<T, Result> {
|
public interface TraceAssertion<T> extends Function<T, Result> {
|
||||||
/**
|
/**
|
||||||
* Returns an assertion that represents the logical negation of this assertion.
|
* Returns an assertion that represents the logical negation of this assertion.
|
||||||
*
|
*
|
||||||
@@ -46,7 +46,7 @@ class Assertions {
|
|||||||
* Checks assertion on a single layers trace entry.
|
* Checks assertion on a single layers trace entry.
|
||||||
*/
|
*/
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> {
|
public interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@ class Assertions {
|
|||||||
* Utility class to store assertions with an identifier to help generate more useful debug
|
* Utility class to store assertions with an identifier to help generate more useful debug
|
||||||
* data when dealing with multiple assertions.
|
* data when dealing with multiple assertions.
|
||||||
*/
|
*/
|
||||||
static class NamedAssertion<T> {
|
public static class NamedAssertion<T> {
|
||||||
final TraceAssertion<T> assertion;
|
public final TraceAssertion<T> assertion;
|
||||||
final String name;
|
public final String name;
|
||||||
|
|
||||||
NamedAssertion(TraceAssertion<T> assertion, String name) {
|
public NamedAssertion(TraceAssertion<T> assertion, String name) {
|
||||||
this.assertion = assertion;
|
this.assertion = assertion;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
@@ -67,21 +67,21 @@ class Assertions {
|
|||||||
/**
|
/**
|
||||||
* Contains the result of an assertion including the reason for failed assertions.
|
* Contains the result of an assertion including the reason for failed assertions.
|
||||||
*/
|
*/
|
||||||
static class Result {
|
public static class Result {
|
||||||
static final String NEGATION_PREFIX = "!";
|
public static final String NEGATION_PREFIX = "!";
|
||||||
final boolean success;
|
public final boolean success;
|
||||||
final long timestamp;
|
public final long timestamp;
|
||||||
final String assertionName;
|
public final String assertionName;
|
||||||
final String reason;
|
public final String reason;
|
||||||
|
|
||||||
Result(boolean success, long timestamp, String assertionName, String reason) {
|
public Result(boolean success, long timestamp, String assertionName, String reason) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.assertionName = assertionName;
|
this.assertionName = assertionName;
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result(boolean success, String reason) {
|
public Result(boolean success, String reason) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
this.assertionName = "";
|
this.assertionName = "";
|
||||||
@@ -91,7 +91,7 @@ class Assertions {
|
|||||||
/**
|
/**
|
||||||
* Returns the negated {@code Result} and adds a negation prefix to the assertion name.
|
* Returns the negated {@code Result} and adds a negation prefix to the assertion name.
|
||||||
*/
|
*/
|
||||||
Result negate() {
|
public Result negate() {
|
||||||
String negatedAssertionName;
|
String negatedAssertionName;
|
||||||
if (this.assertionName.startsWith(NEGATION_PREFIX)) {
|
if (this.assertionName.startsWith(NEGATION_PREFIX)) {
|
||||||
negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1);
|
negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1);
|
||||||
@@ -101,11 +101,11 @@ class Assertions {
|
|||||||
return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason);
|
return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean passed() {
|
public boolean passed() {
|
||||||
return this.success;
|
return this.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean failed() {
|
public boolean failed() {
|
||||||
return !this.success;
|
return !this.success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ public class AssertionsChecker<T extends ITraceEntry> {
|
|||||||
private AssertionOption mOption = AssertionOption.NONE;
|
private AssertionOption mOption = AssertionOption.NONE;
|
||||||
private List<NamedAssertion<T>> mAssertions = new LinkedList<>();
|
private List<NamedAssertion<T>> mAssertions = new LinkedList<>();
|
||||||
|
|
||||||
void add(Assertions.TraceAssertion<T> assertion, String name) {
|
public void add(Assertions.TraceAssertion<T> assertion, String name) {
|
||||||
mAssertions.add(new NamedAssertion<>(assertion, name));
|
mAssertions.add(new NamedAssertion<>(assertion, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void filterByRange(long startTime, long endTime) {
|
public void filterByRange(long startTime, long endTime) {
|
||||||
mFilterEntriesByRange = true;
|
mFilterEntriesByRange = true;
|
||||||
mFilterStartTime = startTime;
|
mFilterStartTime = startTime;
|
||||||
mFilterEndTime = endTime;
|
mFilterEndTime = endTime;
|
||||||
@@ -75,7 +75,7 @@ public class AssertionsChecker<T extends ITraceEntry> {
|
|||||||
* @param entries list of entries to perform assertions on
|
* @param entries list of entries to perform assertions on
|
||||||
* @return list of failed assertion results
|
* @return list of failed assertion results
|
||||||
*/
|
*/
|
||||||
List<Result> test(List<T> entries) {
|
public List<Result> test(List<T> entries) {
|
||||||
List<T> filteredEntries;
|
List<T> filteredEntries;
|
||||||
List<Result> failures;
|
List<Result> failures;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker;
|
|||||||
/**
|
/**
|
||||||
* Common interface for Layer and WindowManager trace entries.
|
* Common interface for Layer and WindowManager trace entries.
|
||||||
*/
|
*/
|
||||||
interface ITraceEntry {
|
public interface ITraceEntry {
|
||||||
/**
|
/**
|
||||||
* @return timestamp of current entry
|
* @return timestamp of current entry
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker;
|
package com.android.server.wm.flicker;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.surfaceflinger.nano.Layers.LayerProto;
|
import android.surfaceflinger.nano.Layers.LayerProto;
|
||||||
import android.surfaceflinger.nano.Layers.RectProto;
|
import android.surfaceflinger.nano.Layers.RectProto;
|
||||||
@@ -25,11 +24,14 @@ import android.surfaceflinger.nano.Layerstrace.LayersTraceFileProto;
|
|||||||
import android.surfaceflinger.nano.Layerstrace.LayersTraceProto;
|
import android.surfaceflinger.nano.Layerstrace.LayersTraceProto;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.Assertions.Result;
|
import com.android.server.wm.flicker.Assertions.Result;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -57,7 +59,7 @@ public class LayersTrace {
|
|||||||
* @param data binary proto data
|
* @param data binary proto data
|
||||||
* @param source Path to source of data for additional debug information
|
* @param source Path to source of data for additional debug information
|
||||||
*/
|
*/
|
||||||
static LayersTrace parseFrom(byte[] data, Path source) {
|
public static LayersTrace parseFrom(byte[] data, Path source) {
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
LayersTraceFileProto fileProto;
|
LayersTraceFileProto fileProto;
|
||||||
try {
|
try {
|
||||||
@@ -79,15 +81,15 @@ public class LayersTrace {
|
|||||||
*
|
*
|
||||||
* @param data binary proto data
|
* @param data binary proto data
|
||||||
*/
|
*/
|
||||||
static LayersTrace parseFrom(byte[] data) {
|
public static LayersTrace parseFrom(byte[] data) {
|
||||||
return parseFrom(data, null);
|
return parseFrom(data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entry> getEntries() {
|
public List<Entry> getEntries() {
|
||||||
return mEntries;
|
return mEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry getEntry(long timestamp) {
|
public Entry getEntry(long timestamp) {
|
||||||
Optional<Entry> entry = mEntries.stream()
|
Optional<Entry> entry = mEntries.stream()
|
||||||
.filter(e -> e.getTimestamp() == timestamp)
|
.filter(e -> e.getTimestamp() == timestamp)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
@@ -97,14 +99,14 @@ public class LayersTrace {
|
|||||||
return entry.get();
|
return entry.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Path> getSource() {
|
public Optional<Path> getSource() {
|
||||||
return Optional.ofNullable(mSource);
|
return Optional.ofNullable(mSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single Layer trace entry.
|
* Represents a single Layer trace entry.
|
||||||
*/
|
*/
|
||||||
static class Entry implements ITraceEntry {
|
public static class Entry implements ITraceEntry {
|
||||||
private long mTimestamp;
|
private long mTimestamp;
|
||||||
private List<Layer> mRootLayers; // hierarchical representation of layers
|
private List<Layer> mRootLayers; // hierarchical representation of layers
|
||||||
private List<Layer> mFlattenedLayers = null;
|
private List<Layer> mFlattenedLayers = null;
|
||||||
@@ -117,7 +119,7 @@ public class LayersTrace {
|
|||||||
/**
|
/**
|
||||||
* Constructs the layer hierarchy from a flattened list of layers.
|
* Constructs the layer hierarchy from a flattened list of layers.
|
||||||
*/
|
*/
|
||||||
static Entry fromFlattenedLayers(long timestamp, LayerProto[] protos) {
|
public static Entry fromFlattenedLayers(long timestamp, LayerProto[] protos) {
|
||||||
SparseArray<Layer> layerMap = new SparseArray<>();
|
SparseArray<Layer> layerMap = new SparseArray<>();
|
||||||
ArrayList<Layer> orphans = new ArrayList<>();
|
ArrayList<Layer> orphans = new ArrayList<>();
|
||||||
for (LayerProto proto : protos) {
|
for (LayerProto proto : protos) {
|
||||||
@@ -181,7 +183,7 @@ public class LayersTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if a region specified by {@code testRect} is covered by all visible layers.
|
* Checks if a region specified by {@code testRect} is covered by all visible layers.
|
||||||
*/
|
*/
|
||||||
Result coversRegion(Rect testRect) {
|
public Result coversRegion(Rect testRect) {
|
||||||
String assertionName = "coversRegion";
|
String assertionName = "coversRegion";
|
||||||
Collection<Layer> layers = asFlattenedLayers();
|
Collection<Layer> layers = asFlattenedLayers();
|
||||||
|
|
||||||
@@ -224,7 +226,7 @@ public class LayersTrace {
|
|||||||
* Checks if a layer with name {@code layerName} has a visible region
|
* Checks if a layer with name {@code layerName} has a visible region
|
||||||
* {@code expectedVisibleRegion}.
|
* {@code expectedVisibleRegion}.
|
||||||
*/
|
*/
|
||||||
Result hasVisibleRegion(String layerName, Rect expectedVisibleRegion) {
|
public Result hasVisibleRegion(String layerName, Rect expectedVisibleRegion) {
|
||||||
String assertionName = "hasVisibleRegion";
|
String assertionName = "hasVisibleRegion";
|
||||||
String reason = "Could not find " + layerName;
|
String reason = "Could not find " + layerName;
|
||||||
for (Layer layer : asFlattenedLayers()) {
|
for (Layer layer : asFlattenedLayers()) {
|
||||||
@@ -252,7 +254,7 @@ public class LayersTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if a layer with name {@code layerName} is visible.
|
* Checks if a layer with name {@code layerName} is visible.
|
||||||
*/
|
*/
|
||||||
Result isVisible(String layerName) {
|
public Result isVisible(String layerName) {
|
||||||
String assertionName = "isVisible";
|
String assertionName = "isVisible";
|
||||||
String reason = "Could not find " + layerName;
|
String reason = "Could not find " + layerName;
|
||||||
for (Layer layer : asFlattenedLayers()) {
|
for (Layer layer : asFlattenedLayers()) {
|
||||||
@@ -277,24 +279,27 @@ public class LayersTrace {
|
|||||||
return mTimestamp;
|
return mTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Layer> getRootLayers() {
|
public List<Layer> getRootLayers() {
|
||||||
return mRootLayers;
|
return mRootLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Layer> asFlattenedLayers() {
|
/**
|
||||||
|
* Returns all layers as a flattened list using a depth first traversal.
|
||||||
|
*/
|
||||||
|
public List<Layer> asFlattenedLayers() {
|
||||||
if (mFlattenedLayers == null) {
|
if (mFlattenedLayers == null) {
|
||||||
mFlattenedLayers = new ArrayList<>();
|
mFlattenedLayers = new LinkedList<>();
|
||||||
ArrayList<Layer> pendingLayers = new ArrayList<>(this.mRootLayers);
|
ArrayList<Layer> pendingLayers = new ArrayList<>(this.mRootLayers);
|
||||||
while (!pendingLayers.isEmpty()) {
|
while (!pendingLayers.isEmpty()) {
|
||||||
Layer layer = pendingLayers.remove(0);
|
Layer layer = pendingLayers.remove(0);
|
||||||
mFlattenedLayers.add(layer);
|
mFlattenedLayers.add(layer);
|
||||||
pendingLayers.addAll(layer.mChildren);
|
pendingLayers.addAll(0, layer.mChildren);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mFlattenedLayers;
|
return mFlattenedLayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect getVisibleBounds(String layerName) {
|
public Rect getVisibleBounds(String layerName) {
|
||||||
List<Layer> layers = asFlattenedLayers();
|
List<Layer> layers = asFlattenedLayers();
|
||||||
for (Layer layer : layers) {
|
for (Layer layer : layers) {
|
||||||
if (layer.mProto.name.contains(layerName) && layer.isVisible()) {
|
if (layer.mProto.name.contains(layerName) && layer.isVisible()) {
|
||||||
@@ -308,12 +313,12 @@ public class LayersTrace {
|
|||||||
/**
|
/**
|
||||||
* Represents a single layer with links to its parent and child layers.
|
* Represents a single layer with links to its parent and child layers.
|
||||||
*/
|
*/
|
||||||
static class Layer {
|
public static class Layer {
|
||||||
@Nullable
|
@Nullable
|
||||||
LayerProto mProto;
|
public LayerProto mProto;
|
||||||
List<Layer> mChildren;
|
public List<Layer> mChildren;
|
||||||
@Nullable
|
@Nullable
|
||||||
Layer mParent = null;
|
public Layer mParent = null;
|
||||||
|
|
||||||
private Layer(LayerProto proto) {
|
private Layer(LayerProto proto) {
|
||||||
this.mProto = proto;
|
this.mProto = proto;
|
||||||
@@ -328,16 +333,16 @@ public class LayersTrace {
|
|||||||
this.mParent = parentLayer;
|
this.mParent = parentLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getId() {
|
public int getId() {
|
||||||
return mProto.id;
|
return mProto.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isActiveBufferEmpty() {
|
public boolean isActiveBufferEmpty() {
|
||||||
return this.mProto.activeBuffer == null || this.mProto.activeBuffer.height == 0
|
return this.mProto.activeBuffer == null || this.mProto.activeBuffer.height == 0
|
||||||
|| this.mProto.activeBuffer.width == 0;
|
|| this.mProto.activeBuffer.width == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isVisibleRegionEmpty() {
|
public boolean isVisibleRegionEmpty() {
|
||||||
if (this.mProto.visibleRegion == null) {
|
if (this.mProto.visibleRegion == null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -345,32 +350,35 @@ public class LayersTrace {
|
|||||||
return visibleRect.height() == 0 || visibleRect.width() == 0;
|
return visibleRect.height() == 0 || visibleRect.width() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isHidden() {
|
public boolean isHidden() {
|
||||||
return (this.mProto.flags & /* FLAG_HIDDEN */ 0x1) != 0x0;
|
return (this.mProto.flags & /* FLAG_HIDDEN */ 0x1) != 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isVisible() {
|
public boolean isVisible() {
|
||||||
return (!isActiveBufferEmpty() || isColorLayer()) &&
|
return (!isActiveBufferEmpty() || isColorLayer())
|
||||||
!isHidden() && this.mProto.color.a > 0 && !isVisibleRegionEmpty();
|
&& !isHidden()
|
||||||
|
&& this.mProto.color != null
|
||||||
|
&& this.mProto.color.a > 0
|
||||||
|
&& !isVisibleRegionEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isColorLayer() {
|
public boolean isColorLayer() {
|
||||||
return this.mProto.type.equals("ColorLayer");
|
return this.mProto.type.equals("ColorLayer");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isRootLayer() {
|
public boolean isRootLayer() {
|
||||||
return mParent == null || mParent.mProto == null;
|
return mParent == null || mParent.mProto == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isInvisible() {
|
public boolean isInvisible() {
|
||||||
return !isVisible();
|
return !isVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isHiddenByParent() {
|
public boolean isHiddenByParent() {
|
||||||
return !isRootLayer() && (mParent.isHidden() || mParent.isHiddenByParent());
|
return !isRootLayer() && (mParent.isHidden() || mParent.isHiddenByParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
String getHiddenByParentReason() {
|
public String getHiddenByParentReason() {
|
||||||
String reason = "Layer " + mProto.name;
|
String reason = "Layer " + mProto.name;
|
||||||
if (isHiddenByParent()) {
|
if (isHiddenByParent()) {
|
||||||
reason += " is hidden by parent: " + mParent.mProto.name;
|
reason += " is hidden by parent: " + mParent.mProto.name;
|
||||||
@@ -380,7 +388,7 @@ public class LayersTrace {
|
|||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getVisibilityReason() {
|
public String getVisibilityReason() {
|
||||||
String reason = "Layer " + mProto.name;
|
String reason = "Layer " + mProto.name;
|
||||||
if (isVisible()) {
|
if (isVisible()) {
|
||||||
reason += " is visible:";
|
reason += " is visible:";
|
||||||
@@ -399,7 +407,7 @@ public class LayersTrace {
|
|||||||
if (isHidden()) {
|
if (isHidden()) {
|
||||||
reason += " flags=" + this.mProto.flags + " (FLAG_HIDDEN set)";
|
reason += " flags=" + this.mProto.flags + " (FLAG_HIDDEN set)";
|
||||||
}
|
}
|
||||||
if (this.mProto.color.a == 0) {
|
if (this.mProto.color == null || this.mProto.color.a == 0) {
|
||||||
reason += " color.a=0";
|
reason += " color.a=0";
|
||||||
}
|
}
|
||||||
if (isVisibleRegionEmpty()) {
|
if (isVisibleRegionEmpty()) {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ package com.android.server.wm.flicker;
|
|||||||
import static com.google.common.truth.Truth.assertAbout;
|
import static com.google.common.truth.Truth.assertAbout;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.Assertions.Result;
|
import com.android.server.wm.flicker.Assertions.Result;
|
||||||
import com.android.server.wm.flicker.LayersTrace.Entry;
|
import com.android.server.wm.flicker.LayersTrace.Entry;
|
||||||
import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
|
import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker;
|
package com.android.server.wm.flicker;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import static com.android.server.wm.flicker.monitor.ITransitionMonitor.OUTPUT_DIR;
|
||||||
import android.support.annotation.VisibleForTesting;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.monitor.ITransitionMonitor;
|
import com.android.server.wm.flicker.monitor.ITransitionMonitor;
|
||||||
@@ -89,7 +91,7 @@ import java.util.List;
|
|||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
class TransitionRunner {
|
public class TransitionRunner {
|
||||||
private static final String TAG = "FLICKER";
|
private static final String TAG = "FLICKER";
|
||||||
private final ScreenRecorder mScreenRecorder;
|
private final ScreenRecorder mScreenRecorder;
|
||||||
private final WindowManagerTraceMonitor mWmTraceMonitor;
|
private final WindowManagerTraceMonitor mWmTraceMonitor;
|
||||||
@@ -128,8 +130,12 @@ class TransitionRunner {
|
|||||||
mTestTag = builder.mTestTag;
|
mTestTag = builder.mTestTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransitionBuilder newBuilder() {
|
public static TransitionBuilder newBuilder() {
|
||||||
return new TransitionBuilder();
|
return newBuilder(OUTPUT_DIR.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TransitionBuilder newBuilder(String outputDir) {
|
||||||
|
return new TransitionBuilder(outputDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -138,7 +144,7 @@ class TransitionRunner {
|
|||||||
*
|
*
|
||||||
* @return itself
|
* @return itself
|
||||||
*/
|
*/
|
||||||
TransitionRunner run() {
|
public TransitionRunner run() {
|
||||||
mResults = new ArrayList<>();
|
mResults = new ArrayList<>();
|
||||||
mAllRunsMonitors.forEach(ITransitionMonitor::start);
|
mAllRunsMonitors.forEach(ITransitionMonitor::start);
|
||||||
mBeforeAlls.forEach(Runnable::run);
|
mBeforeAlls.forEach(Runnable::run);
|
||||||
@@ -159,8 +165,7 @@ class TransitionRunner {
|
|||||||
mAfterAlls.forEach(Runnable::run);
|
mAfterAlls.forEach(Runnable::run);
|
||||||
mAllRunsMonitors.forEach(monitor -> {
|
mAllRunsMonitors.forEach(monitor -> {
|
||||||
monitor.stop();
|
monitor.stop();
|
||||||
Path path = monitor.save(mTestTag);
|
monitor.save(mTestTag);
|
||||||
Log.e(TAG, "Video saved to " + path.toString());
|
|
||||||
});
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -170,7 +175,7 @@ class TransitionRunner {
|
|||||||
*
|
*
|
||||||
* @return list of transition results.
|
* @return list of transition results.
|
||||||
*/
|
*/
|
||||||
List<TransitionResult> getResults() {
|
public List<TransitionResult> getResults() {
|
||||||
if (mResults == null) {
|
if (mResults == null) {
|
||||||
throw new IllegalStateException("Results do not exist!");
|
throw new IllegalStateException("Results do not exist!");
|
||||||
}
|
}
|
||||||
@@ -182,7 +187,7 @@ class TransitionRunner {
|
|||||||
*
|
*
|
||||||
* @return list of transition results.
|
* @return list of transition results.
|
||||||
*/
|
*/
|
||||||
void deleteResults() {
|
public void deleteResults() {
|
||||||
if (mResults == null) {
|
if (mResults == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -228,33 +233,33 @@ class TransitionRunner {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static class TransitionResult {
|
public static class TransitionResult {
|
||||||
@Nullable
|
@Nullable
|
||||||
final Path layersTrace;
|
public final Path layersTrace;
|
||||||
@Nullable
|
@Nullable
|
||||||
final Path windowManagerTrace;
|
public final Path windowManagerTrace;
|
||||||
@Nullable
|
@Nullable
|
||||||
final Path screenCaptureVideo;
|
public final Path screenCaptureVideo;
|
||||||
private boolean flaggedForSaving;
|
private boolean flaggedForSaving;
|
||||||
|
|
||||||
TransitionResult(@Nullable Path layersTrace, @Nullable Path windowManagerTrace,
|
public TransitionResult(@Nullable Path layersTrace, @Nullable Path windowManagerTrace,
|
||||||
@Nullable Path screenCaptureVideo) {
|
@Nullable Path screenCaptureVideo) {
|
||||||
this.layersTrace = layersTrace;
|
this.layersTrace = layersTrace;
|
||||||
this.windowManagerTrace = windowManagerTrace;
|
this.windowManagerTrace = windowManagerTrace;
|
||||||
this.screenCaptureVideo = screenCaptureVideo;
|
this.screenCaptureVideo = screenCaptureVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flagForSaving() {
|
public void flagForSaving() {
|
||||||
flaggedForSaving = true;
|
flaggedForSaving = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean canDelete() {
|
public boolean canDelete() {
|
||||||
return !flaggedForSaving;
|
return !flaggedForSaving;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean layersTraceExists() {
|
public boolean layersTraceExists() {
|
||||||
return layersTrace != null && layersTrace.toFile().exists();
|
return layersTrace != null && layersTrace.toFile().exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] getLayersTrace() {
|
public byte[] getLayersTrace() {
|
||||||
try {
|
try {
|
||||||
return Files.toByteArray(this.layersTrace.toFile());
|
return Files.toByteArray(this.layersTrace.toFile());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -262,11 +267,11 @@ class TransitionRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Path getLayersTracePath() {
|
public Path getLayersTracePath() {
|
||||||
return layersTrace;
|
return layersTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean windowManagerTraceExists() {
|
public boolean windowManagerTraceExists() {
|
||||||
return windowManagerTrace != null && windowManagerTrace.toFile().exists();
|
return windowManagerTrace != null && windowManagerTrace.toFile().exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,19 +283,19 @@ class TransitionRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Path getWindowManagerTracePath() {
|
public Path getWindowManagerTracePath() {
|
||||||
return windowManagerTrace;
|
return windowManagerTrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean screenCaptureVideoExists() {
|
public boolean screenCaptureVideoExists() {
|
||||||
return screenCaptureVideo != null && screenCaptureVideo.toFile().exists();
|
return screenCaptureVideo != null && screenCaptureVideo.toFile().exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
Path screenCaptureVideoPath() {
|
public Path screenCaptureVideoPath() {
|
||||||
return screenCaptureVideo;
|
return screenCaptureVideo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete() {
|
public void delete() {
|
||||||
if (layersTraceExists()) layersTrace.toFile().delete();
|
if (layersTraceExists()) layersTrace.toFile().delete();
|
||||||
if (windowManagerTraceExists()) windowManagerTrace.toFile().delete();
|
if (windowManagerTraceExists()) windowManagerTrace.toFile().delete();
|
||||||
if (screenCaptureVideoExists()) screenCaptureVideo.toFile().delete();
|
if (screenCaptureVideoExists()) screenCaptureVideo.toFile().delete();
|
||||||
@@ -300,7 +305,7 @@ class TransitionRunner {
|
|||||||
/**
|
/**
|
||||||
* Builds a {@link TransitionRunner} instance.
|
* Builds a {@link TransitionRunner} instance.
|
||||||
*/
|
*/
|
||||||
static class TransitionBuilder {
|
public static class TransitionBuilder {
|
||||||
private ScreenRecorder mScreenRecorder;
|
private ScreenRecorder mScreenRecorder;
|
||||||
private WindowManagerTraceMonitor mWmTraceMonitor;
|
private WindowManagerTraceMonitor mWmTraceMonitor;
|
||||||
private LayersTraceMonitor mLayersTraceMonitor;
|
private LayersTraceMonitor mLayersTraceMonitor;
|
||||||
@@ -323,15 +328,15 @@ class TransitionRunner {
|
|||||||
|
|
||||||
private boolean mRecordAllRuns = false;
|
private boolean mRecordAllRuns = false;
|
||||||
|
|
||||||
TransitionBuilder() {
|
public TransitionBuilder(String outputDir) {
|
||||||
mScreenRecorder = new ScreenRecorder();
|
mScreenRecorder = new ScreenRecorder();
|
||||||
mWmTraceMonitor = new WindowManagerTraceMonitor();
|
mWmTraceMonitor = new WindowManagerTraceMonitor(outputDir);
|
||||||
mLayersTraceMonitor = new LayersTraceMonitor();
|
mLayersTraceMonitor = new LayersTraceMonitor(outputDir);
|
||||||
mFrameStatsMonitor = new
|
mFrameStatsMonitor = new
|
||||||
WindowAnimationFrameStatsMonitor(InstrumentationRegistry.getInstrumentation());
|
WindowAnimationFrameStatsMonitor(InstrumentationRegistry.getInstrumentation());
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionRunner build() {
|
public TransitionRunner build() {
|
||||||
if (mCaptureWindowManagerTrace) {
|
if (mCaptureWindowManagerTrace) {
|
||||||
mPerRunMonitors.add(mWmTraceMonitor);
|
mPerRunMonitors.add(mWmTraceMonitor);
|
||||||
}
|
}
|
||||||
@@ -355,52 +360,52 @@ class TransitionRunner {
|
|||||||
return new TransitionRunner(this);
|
return new TransitionRunner(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder runBeforeAll(Runnable runnable) {
|
public TransitionBuilder runBeforeAll(Runnable runnable) {
|
||||||
mBeforeAlls.add(runnable);
|
mBeforeAlls.add(runnable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder runBefore(Runnable runnable) {
|
public TransitionBuilder runBefore(Runnable runnable) {
|
||||||
mBefores.add(runnable);
|
mBefores.add(runnable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder run(Runnable runnable) {
|
public TransitionBuilder run(Runnable runnable) {
|
||||||
mTransitions.add(runnable);
|
mTransitions.add(runnable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder runAfter(Runnable runnable) {
|
public TransitionBuilder runAfter(Runnable runnable) {
|
||||||
mAfters.add(runnable);
|
mAfters.add(runnable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder runAfterAll(Runnable runnable) {
|
public TransitionBuilder runAfterAll(Runnable runnable) {
|
||||||
mAfterAlls.add(runnable);
|
mAfterAlls.add(runnable);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder repeat(int iterations) {
|
public TransitionBuilder repeat(int iterations) {
|
||||||
mIterations = iterations;
|
mIterations = iterations;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder skipWindowManagerTrace() {
|
public TransitionBuilder skipWindowManagerTrace() {
|
||||||
mCaptureWindowManagerTrace = false;
|
mCaptureWindowManagerTrace = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder skipLayersTrace() {
|
public TransitionBuilder skipLayersTrace() {
|
||||||
mCaptureLayersTrace = false;
|
mCaptureLayersTrace = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder includeJankyRuns() {
|
public TransitionBuilder includeJankyRuns() {
|
||||||
mRunJankFree = false;
|
mRunJankFree = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder recordEachRun() {
|
public TransitionBuilder recordEachRun() {
|
||||||
if (mRecordAllRuns) {
|
if (mRecordAllRuns) {
|
||||||
throw new IllegalArgumentException("Invalid option with recordAllRuns");
|
throw new IllegalArgumentException("Invalid option with recordAllRuns");
|
||||||
}
|
}
|
||||||
@@ -408,7 +413,7 @@ class TransitionRunner {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder recordAllRuns() {
|
public TransitionBuilder recordAllRuns() {
|
||||||
if (mRecordEachRun) {
|
if (mRecordEachRun) {
|
||||||
throw new IllegalArgumentException("Invalid option with recordEachRun");
|
throw new IllegalArgumentException("Invalid option with recordEachRun");
|
||||||
}
|
}
|
||||||
@@ -416,7 +421,11 @@ class TransitionRunner {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransitionBuilder withTag(String testTag) {
|
public TransitionBuilder withTag(String testTag) {
|
||||||
|
if (testTag.contains(" ")) {
|
||||||
|
throw new IllegalArgumentException("The test tag can not contain spaces since it "
|
||||||
|
+ "is a part of the file name");
|
||||||
|
}
|
||||||
mTestTag = testTag;
|
mTestTag = testTag;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker;
|
package com.android.server.wm.flicker;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.Assertions.Result;
|
import com.android.server.wm.flicker.Assertions.Result;
|
||||||
import com.android.server.wm.nano.AppWindowTokenProto;
|
import com.android.server.wm.nano.AppWindowTokenProto;
|
||||||
@@ -58,7 +58,7 @@ public class WindowManagerTrace {
|
|||||||
* @param data binary proto data
|
* @param data binary proto data
|
||||||
* @param source Path to source of data for additional debug information
|
* @param source Path to source of data for additional debug information
|
||||||
*/
|
*/
|
||||||
static WindowManagerTrace parseFrom(byte[] data, Path source) {
|
public static WindowManagerTrace parseFrom(byte[] data, Path source) {
|
||||||
List<Entry> entries = new ArrayList<>();
|
List<Entry> entries = new ArrayList<>();
|
||||||
|
|
||||||
WindowManagerTraceFileProto fileProto;
|
WindowManagerTraceFileProto fileProto;
|
||||||
@@ -73,7 +73,7 @@ public class WindowManagerTrace {
|
|||||||
return new WindowManagerTrace(entries, source);
|
return new WindowManagerTrace(entries, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static WindowManagerTrace parseFrom(byte[] data) {
|
public static WindowManagerTrace parseFrom(byte[] data) {
|
||||||
return parseFrom(data, null);
|
return parseFrom(data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ public class WindowManagerTrace {
|
|||||||
return mEntries;
|
return mEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry getEntry(long timestamp) {
|
public Entry getEntry(long timestamp) {
|
||||||
Optional<Entry> entry = mEntries.stream()
|
Optional<Entry> entry = mEntries.stream()
|
||||||
.filter(e -> e.getTimestamp() == timestamp)
|
.filter(e -> e.getTimestamp() == timestamp)
|
||||||
.findFirst();
|
.findFirst();
|
||||||
@@ -91,17 +91,17 @@ public class WindowManagerTrace {
|
|||||||
return entry.get();
|
return entry.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Path> getSource() {
|
public Optional<Path> getSource() {
|
||||||
return Optional.ofNullable(mSource);
|
return Optional.ofNullable(mSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a single WindowManager trace entry.
|
* Represents a single WindowManager trace entry.
|
||||||
*/
|
*/
|
||||||
static class Entry implements ITraceEntry {
|
public static class Entry implements ITraceEntry {
|
||||||
private final WindowManagerTraceProto mProto;
|
private final WindowManagerTraceProto mProto;
|
||||||
|
|
||||||
Entry(WindowManagerTraceProto proto) {
|
public Entry(WindowManagerTraceProto proto) {
|
||||||
mProto = proto;
|
mProto = proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ public class WindowManagerTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if aboveAppWindow with {@code windowTitle} is visible.
|
* Checks if aboveAppWindow with {@code windowTitle} is visible.
|
||||||
*/
|
*/
|
||||||
Result isAboveAppWindowVisible(String windowTitle) {
|
public Result isAboveAppWindowVisible(String windowTitle) {
|
||||||
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
||||||
.rootWindowContainer
|
.rootWindowContainer
|
||||||
.displays[DEFAULT_DISPLAY].aboveAppWindows;
|
.displays[DEFAULT_DISPLAY].aboveAppWindows;
|
||||||
@@ -173,7 +173,7 @@ public class WindowManagerTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if belowAppWindow with {@code windowTitle} is visible.
|
* Checks if belowAppWindow with {@code windowTitle} is visible.
|
||||||
*/
|
*/
|
||||||
Result isBelowAppWindowVisible(String windowTitle) {
|
public Result isBelowAppWindowVisible(String windowTitle) {
|
||||||
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
||||||
.rootWindowContainer
|
.rootWindowContainer
|
||||||
.displays[DEFAULT_DISPLAY].belowAppWindows;
|
.displays[DEFAULT_DISPLAY].belowAppWindows;
|
||||||
@@ -185,7 +185,7 @@ public class WindowManagerTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if imeWindow with {@code windowTitle} is visible.
|
* Checks if imeWindow with {@code windowTitle} is visible.
|
||||||
*/
|
*/
|
||||||
Result isImeWindowVisible(String windowTitle) {
|
public Result isImeWindowVisible(String windowTitle) {
|
||||||
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
WindowTokenProto[] windowTokenProtos = mProto.windowManagerService
|
||||||
.rootWindowContainer
|
.rootWindowContainer
|
||||||
.displays[DEFAULT_DISPLAY].imeWindows;
|
.displays[DEFAULT_DISPLAY].imeWindows;
|
||||||
@@ -197,7 +197,7 @@ public class WindowManagerTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if app window with {@code windowTitle} is on top.
|
* Checks if app window with {@code windowTitle} is on top.
|
||||||
*/
|
*/
|
||||||
Result isVisibleAppWindowOnTop(String windowTitle) {
|
public Result isVisibleAppWindowOnTop(String windowTitle) {
|
||||||
String topAppWindow = getTopVisibleAppWindow();
|
String topAppWindow = getTopVisibleAppWindow();
|
||||||
boolean success = topAppWindow.contains(windowTitle);
|
boolean success = topAppWindow.contains(windowTitle);
|
||||||
String reason = "wanted=" + windowTitle + " found=" + topAppWindow;
|
String reason = "wanted=" + windowTitle + " found=" + topAppWindow;
|
||||||
@@ -207,7 +207,7 @@ public class WindowManagerTrace {
|
|||||||
/**
|
/**
|
||||||
* Checks if app window with {@code windowTitle} is visible.
|
* Checks if app window with {@code windowTitle} is visible.
|
||||||
*/
|
*/
|
||||||
Result isAppWindowVisible(String windowTitle) {
|
public Result isAppWindowVisible(String windowTitle) {
|
||||||
final String assertionName = "isAppWindowVisible";
|
final String assertionName = "isAppWindowVisible";
|
||||||
boolean titleFound = false;
|
boolean titleFound = false;
|
||||||
StackProto[] stacks = mProto.windowManagerService.rootWindowContainer
|
StackProto[] stacks = mProto.windowManagerService.rootWindowContainer
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ import androidx.test.InstrumentationRegistry;
|
|||||||
/**
|
/**
|
||||||
* Helper functions to retrieve system window sizes and positions.
|
* Helper functions to retrieve system window sizes and positions.
|
||||||
*/
|
*/
|
||||||
class WindowUtils {
|
public class WindowUtils {
|
||||||
|
|
||||||
static Rect getDisplayBounds() {
|
public static Rect getDisplayBounds() {
|
||||||
Point display = new Point();
|
Point display = new Point();
|
||||||
WindowManager wm =
|
WindowManager wm =
|
||||||
(WindowManager) InstrumentationRegistry.getContext().getSystemService(
|
(WindowManager) InstrumentationRegistry.getContext().getSystemService(
|
||||||
@@ -46,7 +46,7 @@ class WindowUtils {
|
|||||||
return wm.getDefaultDisplay().getRotation();
|
return wm.getDefaultDisplay().getRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rect getDisplayBounds(int requestedRotation) {
|
public static Rect getDisplayBounds(int requestedRotation) {
|
||||||
Rect displayBounds = getDisplayBounds();
|
Rect displayBounds = getDisplayBounds();
|
||||||
int currentDisplayRotation = getCurrentRotation();
|
int currentDisplayRotation = getCurrentRotation();
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class WindowUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Rect getAppPosition(int requestedRotation) {
|
public static Rect getAppPosition(int requestedRotation) {
|
||||||
Rect displayBounds = getDisplayBounds();
|
Rect displayBounds = getDisplayBounds();
|
||||||
int currentDisplayRotation = getCurrentRotation();
|
int currentDisplayRotation = getCurrentRotation();
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ class WindowUtils {
|
|||||||
return new Rect(0, 0, displayBounds.width(), displayBounds.height());
|
return new Rect(0, 0, displayBounds.width(), displayBounds.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rect getStatusBarPosition(int requestedRotation) {
|
public static Rect getStatusBarPosition(int requestedRotation) {
|
||||||
Resources resources = InstrumentationRegistry.getContext().getResources();
|
Resources resources = InstrumentationRegistry.getContext().getResources();
|
||||||
String resourceName;
|
String resourceName;
|
||||||
Rect displayBounds = getDisplayBounds();
|
Rect displayBounds = getDisplayBounds();
|
||||||
@@ -104,7 +104,7 @@ class WindowUtils {
|
|||||||
return new Rect(0, 0, width, height);
|
return new Rect(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Rect getNavigationBarPosition(int requestedRotation) {
|
public static Rect getNavigationBarPosition(int requestedRotation) {
|
||||||
Resources resources = InstrumentationRegistry.getContext().getResources();
|
Resources resources = InstrumentationRegistry.getContext().getResources();
|
||||||
Rect displayBounds = getDisplayBounds();
|
Rect displayBounds = getDisplayBounds();
|
||||||
int displayWidth = Math.min(displayBounds.width(), displayBounds.height());
|
int displayWidth = Math.min(displayBounds.width(), displayBounds.height());
|
||||||
@@ -129,13 +129,13 @@ class WindowUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getNavigationBarHeight() {
|
public static int getNavigationBarHeight() {
|
||||||
Resources resources = InstrumentationRegistry.getContext().getResources();
|
Resources resources = InstrumentationRegistry.getContext().getResources();
|
||||||
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
|
||||||
return resources.getDimensionPixelSize(resourceId);
|
return resources.getDimensionPixelSize(resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getDockedStackDividerInset() {
|
public static int getDockedStackDividerInset() {
|
||||||
Resources resources = InstrumentationRegistry.getContext().getResources();
|
Resources resources = InstrumentationRegistry.getContext().getResources();
|
||||||
int resourceId = resources.getIdentifier("docked_stack_divider_insets", "dimen",
|
int resourceId = resources.getIdentifier("docked_stack_divider_insets", "dimen",
|
||||||
"android");
|
"android");
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker;
|
|||||||
import static com.google.common.truth.Truth.assertAbout;
|
import static com.google.common.truth.Truth.assertAbout;
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.Assertions.Result;
|
import com.android.server.wm.flicker.Assertions.Result;
|
||||||
import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
|
import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.server.wm.flicker;
|
package com.android.server.wm.flicker.helpers;
|
||||||
|
|
||||||
import static android.os.SystemClock.sleep;
|
import static android.os.SystemClock.sleep;
|
||||||
import static android.system.helpers.OverviewHelper.isRecentsInLauncher;
|
import static android.system.helpers.OverviewHelper.isRecentsInLauncher;
|
||||||
@@ -44,6 +44,8 @@ import android.view.ViewConfiguration;
|
|||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.android.server.wm.flicker.WindowUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of UI Automation helper functions.
|
* Collection of UI Automation helper functions.
|
||||||
*/
|
*/
|
||||||
@@ -70,14 +72,14 @@ public class AutomationUtils {
|
|||||||
* This removes some delays when using the UIAutomator library required to create fast UI
|
* This removes some delays when using the UIAutomator library required to create fast UI
|
||||||
* transitions.
|
* transitions.
|
||||||
*/
|
*/
|
||||||
static void setFastWait() {
|
public static void setFastWait() {
|
||||||
Configurator.getInstance().setWaitForIdleTimeout(0);
|
Configurator.getInstance().setWaitForIdleTimeout(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverts {@link android.app.UiAutomation#waitForIdle(long, long)} to default behavior.
|
* Reverts {@link android.app.UiAutomation#waitForIdle(long, long)} to default behavior.
|
||||||
*/
|
*/
|
||||||
static void setDefaultWait() {
|
public static void setDefaultWait() {
|
||||||
Configurator.getInstance().setWaitForIdleTimeout(10000);
|
Configurator.getInstance().setWaitForIdleTimeout(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +126,7 @@ public class AutomationUtils {
|
|||||||
device.waitForIdle();
|
device.waitForIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearRecents(UiDevice device) {
|
public static void clearRecents(UiDevice device) {
|
||||||
if (isQuickstepEnabled(device)) {
|
if (isQuickstepEnabled(device)) {
|
||||||
openQuickstep(device);
|
openQuickstep(device);
|
||||||
|
|
||||||
@@ -201,7 +203,7 @@ public class AutomationUtils {
|
|||||||
sleep(2000);
|
sleep(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resizeSplitScreen(UiDevice device, Rational windowHeightRatio) {
|
public static void resizeSplitScreen(UiDevice device, Rational windowHeightRatio) {
|
||||||
BySelector dividerSelector = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle");
|
BySelector dividerSelector = By.res(SYSTEMUI_PACKAGE, "docked_divider_handle");
|
||||||
UiObject2 divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
|
UiObject2 divider = device.wait(Until.findObject(dividerSelector), FIND_TIMEOUT);
|
||||||
assertNotNull("Unable to find Split screen divider", divider);
|
assertNotNull("Unable to find Split screen divider", divider);
|
||||||
@@ -218,7 +220,7 @@ public class AutomationUtils {
|
|||||||
sleep(2000);
|
sleep(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closePipWindow(UiDevice device) {
|
public static void closePipWindow(UiDevice device) {
|
||||||
UiObject2 pipWindow = device.findObject(
|
UiObject2 pipWindow = device.findObject(
|
||||||
By.res(SYSTEMUI_PACKAGE, "background"));
|
By.res(SYSTEMUI_PACKAGE, "background"));
|
||||||
pipWindow.click();
|
pipWindow.click();
|
||||||
@@ -229,7 +231,7 @@ public class AutomationUtils {
|
|||||||
sleep(2000);
|
sleep(2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expandPipWindow(UiDevice device) {
|
public static void expandPipWindow(UiDevice device) {
|
||||||
UiObject2 pipWindow = device.findObject(
|
UiObject2 pipWindow = device.findObject(
|
||||||
By.res(SYSTEMUI_PACKAGE, "background"));
|
By.res(SYSTEMUI_PACKAGE, "background"));
|
||||||
pipWindow.click();
|
pipWindow.click();
|
||||||
@@ -16,21 +16,22 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker.monitor;
|
package com.android.server.wm.flicker.monitor;
|
||||||
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.os.Parcel;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.view.IWindowManager;
|
||||||
import android.util.Log;
|
import android.view.WindowManagerGlobal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captures Layers trace from SurfaceFlinger.
|
* Captures Layers trace from SurfaceFlinger.
|
||||||
*/
|
*/
|
||||||
public class LayersTraceMonitor extends TraceMonitor {
|
public class LayersTraceMonitor extends TraceMonitor {
|
||||||
private static final String TAG = "LayersTraceMonitor";
|
private IWindowManager mWm = WindowManagerGlobal.getWindowManagerService();
|
||||||
private IBinder mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
|
|
||||||
|
|
||||||
public LayersTraceMonitor() {
|
public LayersTraceMonitor() {
|
||||||
traceFileName = "layers_trace.pb";
|
this(OUTPUT_DIR.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public LayersTraceMonitor(String outputDir) {
|
||||||
|
super(outputDir, "layers_trace.pb");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,30 +46,19 @@ public class LayersTraceMonitor extends TraceMonitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled() throws RemoteException {
|
public boolean isEnabled() throws RemoteException {
|
||||||
Parcel data = Parcel.obtain();
|
try {
|
||||||
Parcel reply = Parcel.obtain();
|
return mWm.isLayerTracing();
|
||||||
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
} catch (RemoteException e) {
|
||||||
mSurfaceFlinger.transact(/* LAYER_TRACE_STATUS_CODE */ 1026,
|
e.printStackTrace();
|
||||||
data, reply, 0 /* flags */);
|
}
|
||||||
return reply.readBoolean();
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEnabled(boolean isEnabled) {
|
private void setEnabled(boolean isEnabled) {
|
||||||
Parcel data = null;
|
|
||||||
try {
|
try {
|
||||||
if (mSurfaceFlinger != null) {
|
mWm.setLayerTracing(isEnabled);
|
||||||
data = Parcel.obtain();
|
|
||||||
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
|
||||||
data.writeInt(isEnabled ? 1 : 0);
|
|
||||||
mSurfaceFlinger.transact( /* LAYER_TRACE_CONTROL_CODE */ 1025,
|
|
||||||
data, null, 0 /* flags */);
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Could not set layer tracing." + e.toString());
|
e.printStackTrace();
|
||||||
} finally {
|
|
||||||
if (data != null) {
|
|
||||||
data.recycle();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,25 +20,25 @@ import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
|
|||||||
|
|
||||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||||
|
|
||||||
import android.support.annotation.VisibleForTesting;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Captures screen contents and saves it as a mp4 video file.
|
* Captures screen contents and saves it as a mp4 video file.
|
||||||
*/
|
*/
|
||||||
public class ScreenRecorder implements ITransitionMonitor {
|
public class ScreenRecorder implements ITransitionMonitor {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final Path DEFAULT_OUTPUT_PATH = OUTPUT_DIR.resolve("transition.mp4");
|
public static final Path DEFAULT_OUTPUT_PATH = OUTPUT_DIR.resolve("transition.mp4");
|
||||||
private static final String TAG = "FLICKER";
|
private static final String TAG = "FLICKER";
|
||||||
private Thread recorderThread;
|
private Thread recorderThread;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static Path getPath(String testTag) {
|
public static Path getPath(String testTag) {
|
||||||
return OUTPUT_DIR.resolve(testTag + ".mp4");
|
return OUTPUT_DIR.resolve(testTag + ".mp4");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,8 +69,10 @@ public class ScreenRecorder implements ITransitionMonitor {
|
|||||||
@Override
|
@Override
|
||||||
public Path save(String testTag) {
|
public Path save(String testTag) {
|
||||||
try {
|
try {
|
||||||
return Files.move(DEFAULT_OUTPUT_PATH, getPath(testTag),
|
Path targetPath = Files.move(DEFAULT_OUTPUT_PATH, getPath(testTag),
|
||||||
REPLACE_EXISTING);
|
REPLACE_EXISTING);
|
||||||
|
Log.i(TAG, "Video saved to " + targetPath.toString());
|
||||||
|
return targetPath;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
|
|||||||
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@@ -34,9 +34,15 @@ public abstract class TraceMonitor implements ITransitionMonitor {
|
|||||||
public static final String TAG = "FLICKER";
|
public static final String TAG = "FLICKER";
|
||||||
private static final String TRACE_DIR = "/data/misc/wmtrace/";
|
private static final String TRACE_DIR = "/data/misc/wmtrace/";
|
||||||
|
|
||||||
String traceFileName;
|
private Path mOutputDir;
|
||||||
|
public String mTraceFileName;
|
||||||
|
|
||||||
abstract boolean isEnabled() throws RemoteException;
|
public abstract boolean isEnabled() throws RemoteException;
|
||||||
|
|
||||||
|
public TraceMonitor(String outputDir, String traceFileName) {
|
||||||
|
mOutputDir = Paths.get(outputDir);
|
||||||
|
mTraceFileName = traceFileName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves trace file to the external storage directory suffixing the name with the testtag
|
* Saves trace file to the external storage directory suffixing the name with the testtag
|
||||||
@@ -53,14 +59,16 @@ public abstract class TraceMonitor implements ITransitionMonitor {
|
|||||||
public Path save(String testTag) {
|
public Path save(String testTag) {
|
||||||
OUTPUT_DIR.toFile().mkdirs();
|
OUTPUT_DIR.toFile().mkdirs();
|
||||||
Path traceFileCopy = getOutputTraceFilePath(testTag);
|
Path traceFileCopy = getOutputTraceFilePath(testTag);
|
||||||
|
|
||||||
|
// Read the input stream fully.
|
||||||
String copyCommand = String.format(Locale.getDefault(), "mv %s%s %s", TRACE_DIR,
|
String copyCommand = String.format(Locale.getDefault(), "mv %s%s %s", TRACE_DIR,
|
||||||
traceFileName, traceFileCopy.toString());
|
mTraceFileName, traceFileCopy.toString());
|
||||||
runShellCommand(copyCommand);
|
runShellCommand(copyCommand);
|
||||||
return traceFileCopy;
|
return traceFileCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Path getOutputTraceFilePath(String testTag) {
|
public Path getOutputTraceFilePath(String testTag) {
|
||||||
return OUTPUT_DIR.resolve(traceFileName + "_" + testTag);
|
return mOutputDir.resolve(mTraceFileName + "_" + testTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,16 +24,20 @@ import android.view.WindowManagerGlobal;
|
|||||||
* Captures WindowManager trace from WindowManager.
|
* Captures WindowManager trace from WindowManager.
|
||||||
*/
|
*/
|
||||||
public class WindowManagerTraceMonitor extends TraceMonitor {
|
public class WindowManagerTraceMonitor extends TraceMonitor {
|
||||||
private IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
|
private IWindowManager mWm = WindowManagerGlobal.getWindowManagerService();
|
||||||
|
|
||||||
public WindowManagerTraceMonitor() {
|
public WindowManagerTraceMonitor() {
|
||||||
traceFileName = "wm_trace.pb";
|
this(OUTPUT_DIR.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowManagerTraceMonitor(String outputDir) {
|
||||||
|
super(outputDir, "wm_trace.pb");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
try {
|
try {
|
||||||
wm.startWindowTrace();
|
mWm.startWindowTrace();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException("Could not start trace", e);
|
throw new RuntimeException("Could not start trace", e);
|
||||||
}
|
}
|
||||||
@@ -42,7 +46,7 @@ public class WindowManagerTraceMonitor extends TraceMonitor {
|
|||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
try {
|
try {
|
||||||
wm.stopWindowTrace();
|
mWm.stopWindowTrace();
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException("Could not stop trace", e);
|
throw new RuntimeException("Could not stop trace", e);
|
||||||
}
|
}
|
||||||
@@ -50,6 +54,6 @@ public class WindowManagerTraceMonitor extends TraceMonitor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEnabled() throws RemoteException{
|
public boolean isEnabled() throws RemoteException{
|
||||||
return wm.isWindowTraceEnabled();
|
return mWm.isWindowTraceEnabled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker.monitor;
|
package com.android.server.wm.flicker.monitor;
|
||||||
|
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.wakeUpAndGoToHomeScreen;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.wakeUpAndGoToHomeScreen;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ package com.android.server.wm.flicker;
|
|||||||
import static android.os.SystemClock.sleep;
|
import static android.os.SystemClock.sleep;
|
||||||
import static android.view.Surface.rotationToString;
|
import static android.view.Surface.rotationToString;
|
||||||
|
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.clearRecents;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.clearRecents;
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.closePipWindow;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.closePipWindow;
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.exitSplitScreen;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.exitSplitScreen;
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.expandPipWindow;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.expandPipWindow;
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.launchSplitScreen;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.launchSplitScreen;
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.stopPackage;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.stopPackage;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -40,6 +40,7 @@ import android.view.Surface;
|
|||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
|
||||||
import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
|
import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
|
||||||
|
import com.android.server.wm.flicker.helpers.AutomationUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of common transitions which can be used to test different apps or scenarios.
|
* Collection of common transitions which can be used to test different apps or scenarios.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.wm.flicker;
|
package com.android.server.wm.flicker;
|
||||||
|
|
||||||
import static com.android.server.wm.flicker.AutomationUtils.setDefaultWait;
|
import static com.android.server.wm.flicker.helpers.AutomationUtils.setDefaultWait;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertWithMessage;
|
import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user