Merge "Remove the local insets sources if the owner dies" into udc-qpr-dev
This commit is contained in:
@@ -688,6 +688,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
.setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)
|
.setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)
|
||||||
.setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE)
|
.setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE)
|
||||||
.setArbitraryRectangle(frame))
|
.setArbitraryRectangle(frame))
|
||||||
|
.setInsetsFrameOwner(owner)
|
||||||
.build();
|
.build();
|
||||||
mHierarchyOps.add(hierarchyOp);
|
mHierarchyOps.add(hierarchyOp);
|
||||||
return this;
|
return this;
|
||||||
@@ -712,6 +713,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER)
|
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER)
|
||||||
.setContainer(receiver.asBinder())
|
.setContainer(receiver.asBinder())
|
||||||
.setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type))
|
.setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type))
|
||||||
|
.setInsetsFrameOwner(owner)
|
||||||
.build();
|
.build();
|
||||||
mHierarchyOps.add(hierarchyOp);
|
mHierarchyOps.add(hierarchyOp);
|
||||||
return this;
|
return this;
|
||||||
@@ -1344,8 +1346,12 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private IBinder mReparent;
|
private IBinder mReparent;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private InsetsFrameProvider mInsetsFrameProvider;
|
private InsetsFrameProvider mInsetsFrameProvider;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private IBinder mInsetsFrameOwner;
|
||||||
|
|
||||||
// Moves/reparents to top of parent when {@code true}, otherwise moves/reparents to bottom.
|
// Moves/reparents to top of parent when {@code true}, otherwise moves/reparents to bottom.
|
||||||
private boolean mToTop;
|
private boolean mToTop;
|
||||||
|
|
||||||
@@ -1478,6 +1484,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
mContainer = copy.mContainer;
|
mContainer = copy.mContainer;
|
||||||
mReparent = copy.mReparent;
|
mReparent = copy.mReparent;
|
||||||
mInsetsFrameProvider = copy.mInsetsFrameProvider;
|
mInsetsFrameProvider = copy.mInsetsFrameProvider;
|
||||||
|
mInsetsFrameOwner = copy.mInsetsFrameOwner;
|
||||||
mToTop = copy.mToTop;
|
mToTop = copy.mToTop;
|
||||||
mReparentTopOnly = copy.mReparentTopOnly;
|
mReparentTopOnly = copy.mReparentTopOnly;
|
||||||
mWindowingModes = copy.mWindowingModes;
|
mWindowingModes = copy.mWindowingModes;
|
||||||
@@ -1496,6 +1503,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
mContainer = in.readStrongBinder();
|
mContainer = in.readStrongBinder();
|
||||||
mReparent = in.readStrongBinder();
|
mReparent = in.readStrongBinder();
|
||||||
mInsetsFrameProvider = in.readTypedObject(InsetsFrameProvider.CREATOR);
|
mInsetsFrameProvider = in.readTypedObject(InsetsFrameProvider.CREATOR);
|
||||||
|
mInsetsFrameOwner = in.readStrongBinder();
|
||||||
mToTop = in.readBoolean();
|
mToTop = in.readBoolean();
|
||||||
mReparentTopOnly = in.readBoolean();
|
mReparentTopOnly = in.readBoolean();
|
||||||
mWindowingModes = in.createIntArray();
|
mWindowingModes = in.createIntArray();
|
||||||
@@ -1527,6 +1535,11 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
return mInsetsFrameProvider;
|
return mInsetsFrameProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public IBinder getInsetsFrameOwner() {
|
||||||
|
return mInsetsFrameOwner;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public IBinder getContainer() {
|
public IBinder getContainer() {
|
||||||
return mContainer;
|
return mContainer;
|
||||||
@@ -1657,7 +1670,8 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER:
|
case HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER:
|
||||||
case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER:
|
case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER:
|
||||||
sb.append("container=").append(mContainer)
|
sb.append("container=").append(mContainer)
|
||||||
.append(" provider=").append(mInsetsFrameProvider);
|
.append(" provider=").append(mInsetsFrameProvider)
|
||||||
|
.append(" owner=").append(mInsetsFrameOwner);
|
||||||
break;
|
break;
|
||||||
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
|
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
|
||||||
sb.append("container=").append(mContainer)
|
sb.append("container=").append(mContainer)
|
||||||
@@ -1697,6 +1711,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
dest.writeStrongBinder(mContainer);
|
dest.writeStrongBinder(mContainer);
|
||||||
dest.writeStrongBinder(mReparent);
|
dest.writeStrongBinder(mReparent);
|
||||||
dest.writeTypedObject(mInsetsFrameProvider, flags);
|
dest.writeTypedObject(mInsetsFrameProvider, flags);
|
||||||
|
dest.writeStrongBinder(mInsetsFrameOwner);
|
||||||
dest.writeBoolean(mToTop);
|
dest.writeBoolean(mToTop);
|
||||||
dest.writeBoolean(mReparentTopOnly);
|
dest.writeBoolean(mReparentTopOnly);
|
||||||
dest.writeIntArray(mWindowingModes);
|
dest.writeIntArray(mWindowingModes);
|
||||||
@@ -1737,8 +1752,12 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private IBinder mReparent;
|
private IBinder mReparent;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private InsetsFrameProvider mInsetsFrameProvider;
|
private InsetsFrameProvider mInsetsFrameProvider;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private IBinder mInsetsFrameOwner;
|
||||||
|
|
||||||
private boolean mToTop;
|
private boolean mToTop;
|
||||||
|
|
||||||
private boolean mReparentTopOnly;
|
private boolean mReparentTopOnly;
|
||||||
@@ -1782,8 +1801,13 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Builder setInsetsFrameProvider(InsetsFrameProvider providers) {
|
Builder setInsetsFrameProvider(InsetsFrameProvider provider) {
|
||||||
mInsetsFrameProvider = providers;
|
mInsetsFrameProvider = provider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Builder setInsetsFrameOwner(IBinder owner) {
|
||||||
|
mInsetsFrameOwner = owner;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1854,6 +1878,7 @@ public final class WindowContainerTransaction implements Parcelable {
|
|||||||
? Arrays.copyOf(mActivityTypes, mActivityTypes.length)
|
? Arrays.copyOf(mActivityTypes, mActivityTypes.length)
|
||||||
: null;
|
: null;
|
||||||
hierarchyOp.mInsetsFrameProvider = mInsetsFrameProvider;
|
hierarchyOp.mInsetsFrameProvider = mInsetsFrameProvider;
|
||||||
|
hierarchyOp.mInsetsFrameOwner = mInsetsFrameOwner;
|
||||||
hierarchyOp.mToTop = mToTop;
|
hierarchyOp.mToTop = mToTop;
|
||||||
hierarchyOp.mReparentTopOnly = mReparentTopOnly;
|
hierarchyOp.mReparentTopOnly = mReparentTopOnly;
|
||||||
hierarchyOp.mLaunchOptions = mLaunchOptions;
|
hierarchyOp.mLaunchOptions = mLaunchOptions;
|
||||||
|
|||||||
@@ -81,7 +81,9 @@ import android.graphics.Point;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Pools;
|
import android.util.Pools;
|
||||||
@@ -174,6 +176,9 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
*/
|
*/
|
||||||
protected SparseArray<InsetsSourceProvider> mInsetsSourceProviders = null;
|
protected SparseArray<InsetsSourceProvider> mInsetsSourceProviders = null;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ArrayMap<IBinder, DeathRecipient> mInsetsOwnerDeathRecipientMap;
|
||||||
|
|
||||||
// List of children for this window container. List is in z-order as the children appear on
|
// List of children for this window container. List is in z-order as the children appear on
|
||||||
// screen with the top-most window container at the tail of the list.
|
// screen with the top-most window container at the tail of the list.
|
||||||
protected final WindowList<E> mChildren = new WindowList<E>();
|
protected final WindowList<E> mChildren = new WindowList<E>();
|
||||||
@@ -419,11 +424,12 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
* Adds an {@link InsetsFrameProvider} which describes what insets should be provided to
|
* Adds an {@link InsetsFrameProvider} which describes what insets should be provided to
|
||||||
* this {@link WindowContainer} and its children.
|
* this {@link WindowContainer} and its children.
|
||||||
*
|
*
|
||||||
* @param provider describes the insets types and the frames.
|
* @param provider describes the insets type and the frame.
|
||||||
|
* @param owner owns the insets source which only exists when the owner is alive.
|
||||||
*/
|
*/
|
||||||
void addLocalInsetsFrameProvider(InsetsFrameProvider provider) {
|
void addLocalInsetsFrameProvider(InsetsFrameProvider provider, IBinder owner) {
|
||||||
if (provider == null) {
|
if (provider == null || owner == null) {
|
||||||
throw new IllegalArgumentException("Insets type not specified.");
|
throw new IllegalArgumentException("Insets provider or owner not specified.");
|
||||||
}
|
}
|
||||||
if (mDisplayContent == null) {
|
if (mDisplayContent == null) {
|
||||||
// This is possible this container is detached when WM shell is responding to a previous
|
// This is possible this container is detached when WM shell is responding to a previous
|
||||||
@@ -432,10 +438,26 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
Slog.w(TAG, "Can't add insets frame provider when detached. " + this);
|
Slog.w(TAG, "Can't add insets frame provider when detached. " + this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mInsetsOwnerDeathRecipientMap == null) {
|
||||||
|
mInsetsOwnerDeathRecipientMap = new ArrayMap<>();
|
||||||
|
}
|
||||||
|
DeathRecipient deathRecipient = mInsetsOwnerDeathRecipientMap.get(owner);
|
||||||
|
if (deathRecipient == null) {
|
||||||
|
deathRecipient = new DeathRecipient(owner);
|
||||||
|
try {
|
||||||
|
owner.linkToDeath(deathRecipient, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Failed to add source for " + provider + " since the owner has died.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInsetsOwnerDeathRecipientMap.put(owner, deathRecipient);
|
||||||
|
}
|
||||||
|
final int id = provider.getId();
|
||||||
|
deathRecipient.addSourceId(id);
|
||||||
if (mLocalInsetsSources == null) {
|
if (mLocalInsetsSources == null) {
|
||||||
mLocalInsetsSources = new SparseArray<>();
|
mLocalInsetsSources = new SparseArray<>();
|
||||||
}
|
}
|
||||||
final int id = provider.getId();
|
|
||||||
if (mLocalInsetsSources.get(id) != null) {
|
if (mLocalInsetsSources.get(id) != null) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "The local insets source for this " + provider
|
Slog.d(TAG, "The local insets source for this " + provider
|
||||||
@@ -448,27 +470,77 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
|
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeLocalInsetsFrameProvider(InsetsFrameProvider provider) {
|
private class DeathRecipient implements IBinder.DeathRecipient {
|
||||||
if (provider == null) {
|
|
||||||
throw new IllegalArgumentException("Insets type not specified.");
|
private final IBinder mOwner;
|
||||||
}
|
private final ArraySet<Integer> mSourceIds = new ArraySet<>();
|
||||||
if (mLocalInsetsSources == null) {
|
|
||||||
return;
|
DeathRecipient(IBinder owner) {
|
||||||
|
mOwner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int id = provider.getId();
|
void addSourceId(int id) {
|
||||||
if (mLocalInsetsSources.get(id) == null) {
|
mSourceIds.add(id);
|
||||||
if (DEBUG) {
|
}
|
||||||
Slog.d(TAG, "Given " + provider + " doesn't have a local insets source.");
|
|
||||||
|
void removeSourceId(int id) {
|
||||||
|
mSourceIds.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasSource() {
|
||||||
|
return !mSourceIds.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
synchronized (mWmService.mGlobalLock) {
|
||||||
|
boolean changed = false;
|
||||||
|
for (int i = mSourceIds.size() - 1; i >= 0; i--) {
|
||||||
|
changed |= removeLocalInsetsSource(mSourceIds.valueAt(i));
|
||||||
|
}
|
||||||
|
mSourceIds.clear();
|
||||||
|
mOwner.unlinkToDeath(this, 0);
|
||||||
|
mInsetsOwnerDeathRecipientMap.remove(mOwner);
|
||||||
|
if (changed && mDisplayContent != null) {
|
||||||
|
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
mLocalInsetsSources.remove(id);
|
}
|
||||||
|
|
||||||
// Update insets if this window is attached.
|
void removeLocalInsetsFrameProvider(InsetsFrameProvider provider, IBinder owner) {
|
||||||
if (mDisplayContent != null) {
|
if (provider == null || owner == null) {
|
||||||
|
throw new IllegalArgumentException("Insets provider or owner not specified.");
|
||||||
|
}
|
||||||
|
final int id = provider.getId();
|
||||||
|
if (removeLocalInsetsSource(id) && mDisplayContent != null) {
|
||||||
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
|
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
|
||||||
}
|
}
|
||||||
|
if (mInsetsOwnerDeathRecipientMap == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final DeathRecipient deathRecipient = mInsetsOwnerDeathRecipientMap.get(owner);
|
||||||
|
if (deathRecipient == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deathRecipient.removeSourceId(id);
|
||||||
|
if (!deathRecipient.hasSource()) {
|
||||||
|
owner.unlinkToDeath(deathRecipient, 0);
|
||||||
|
mInsetsOwnerDeathRecipientMap.remove(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean removeLocalInsetsSource(int id) {
|
||||||
|
if (mLocalInsetsSources == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mLocalInsetsSources.removeReturnOld(id) == null) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Given id " + Integer.toHexString(id) + " doesn't exist.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1090,7 +1090,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
+ container);
|
+ container);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
container.addLocalInsetsFrameProvider(hop.getInsetsFrameProvider());
|
container.addLocalInsetsFrameProvider(
|
||||||
|
hop.getInsetsFrameProvider(), hop.getInsetsFrameOwner());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER: {
|
case HIERARCHY_OP_TYPE_REMOVE_INSETS_FRAME_PROVIDER: {
|
||||||
@@ -1100,7 +1101,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
|
|||||||
+ container);
|
+ container);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
container.removeLocalInsetsFrameProvider(hop.getInsetsFrameProvider());
|
container.removeLocalInsetsFrameProvider(
|
||||||
|
hop.getInsetsFrameProvider(), hop.getInsetsFrameOwner());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: {
|
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: {
|
||||||
|
|||||||
@@ -64,10 +64,19 @@ import static org.junit.Assert.assertNull;
|
|||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.DeadObjectException;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.IInterface;
|
||||||
|
import android.os.Parcel;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
|
import android.os.ShellCallback;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.view.IRemoteAnimationFinishedCallback;
|
import android.view.IRemoteAnimationFinishedCallback;
|
||||||
import android.view.IRemoteAnimationRunner;
|
import android.view.IRemoteAnimationRunner;
|
||||||
@@ -87,8 +96,10 @@ import org.junit.runner.RunWith;
|
|||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1404,7 +1415,7 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLocalInsetsSourceProvider() {
|
public void testAddLocalInsetsFrameProvider() {
|
||||||
/*
|
/*
|
||||||
___ rootTask _______________________________________________
|
___ rootTask _______________________________________________
|
||||||
| | | |
|
| | | |
|
||||||
@@ -1435,19 +1446,20 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
TYPE_BASE_APPLICATION);
|
TYPE_BASE_APPLICATION);
|
||||||
attrs2.setTitle("AppWindow2");
|
attrs2.setTitle("AppWindow2");
|
||||||
activity2.addWindow(createWindowState(attrs2, activity2));
|
activity2.addWindow(createWindowState(attrs2, activity2));
|
||||||
|
final Binder owner = new Binder();
|
||||||
Rect genericOverlayInsetsRect1 = new Rect(0, 200, 1080, 700);
|
Rect genericOverlayInsetsRect1 = new Rect(0, 200, 1080, 700);
|
||||||
Rect genericOverlayInsetsRect2 = new Rect(0, 0, 1080, 200);
|
Rect genericOverlayInsetsRect2 = new Rect(0, 0, 1080, 200);
|
||||||
final InsetsFrameProvider provider1 =
|
final InsetsFrameProvider provider1 =
|
||||||
new InsetsFrameProvider(null, 1, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 1, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(genericOverlayInsetsRect1);
|
.setArbitraryRectangle(genericOverlayInsetsRect1);
|
||||||
final InsetsFrameProvider provider2 =
|
final InsetsFrameProvider provider2 =
|
||||||
new InsetsFrameProvider(null, 2, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 2, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(genericOverlayInsetsRect2);
|
.setArbitraryRectangle(genericOverlayInsetsRect2);
|
||||||
final int sourceId1 = provider1.getId();
|
final int sourceId1 = provider1.getId();
|
||||||
final int sourceId2 = provider2.getId();
|
final int sourceId2 = provider2.getId();
|
||||||
|
|
||||||
rootTask.addLocalInsetsFrameProvider(provider1);
|
rootTask.addLocalInsetsFrameProvider(provider1, owner);
|
||||||
container.addLocalInsetsFrameProvider(provider2);
|
container.addLocalInsetsFrameProvider(provider2, owner);
|
||||||
|
|
||||||
InsetsSource genericOverlayInsetsProvider1Source = new InsetsSource(
|
InsetsSource genericOverlayInsetsProvider1Source = new InsetsSource(
|
||||||
sourceId1, systemOverlays());
|
sourceId1, systemOverlays());
|
||||||
@@ -1479,7 +1491,7 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLocalInsetsSourceProvider_sameType_replacesInsets() {
|
public void testAddLocalInsetsFrameProvider_sameType_replacesInsets() {
|
||||||
/*
|
/*
|
||||||
___ rootTask ________________________________________
|
___ rootTask ________________________________________
|
||||||
| | |
|
| | |
|
||||||
@@ -1494,24 +1506,25 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
attrs.setTitle("AppWindow0");
|
attrs.setTitle("AppWindow0");
|
||||||
activity0.addWindow(createWindowState(attrs, activity0));
|
activity0.addWindow(createWindowState(attrs, activity0));
|
||||||
|
|
||||||
|
final Binder owner = new Binder();
|
||||||
final Rect genericOverlayInsetsRect1 = new Rect(0, 200, 1080, 700);
|
final Rect genericOverlayInsetsRect1 = new Rect(0, 200, 1080, 700);
|
||||||
final Rect genericOverlayInsetsRect2 = new Rect(0, 0, 1080, 200);
|
final Rect genericOverlayInsetsRect2 = new Rect(0, 0, 1080, 200);
|
||||||
final InsetsFrameProvider provider1 =
|
final InsetsFrameProvider provider1 =
|
||||||
new InsetsFrameProvider(null, 1, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 1, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(genericOverlayInsetsRect1);
|
.setArbitraryRectangle(genericOverlayInsetsRect1);
|
||||||
final InsetsFrameProvider provider2 =
|
final InsetsFrameProvider provider2 =
|
||||||
new InsetsFrameProvider(null, 1, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 1, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(genericOverlayInsetsRect2);
|
.setArbitraryRectangle(genericOverlayInsetsRect2);
|
||||||
final int sourceId1 = provider1.getId();
|
final int sourceId1 = provider1.getId();
|
||||||
final int sourceId2 = provider2.getId();
|
final int sourceId2 = provider2.getId();
|
||||||
|
|
||||||
rootTask.addLocalInsetsFrameProvider(provider1);
|
rootTask.addLocalInsetsFrameProvider(provider1, owner);
|
||||||
activity0.forAllWindows(window -> {
|
activity0.forAllWindows(window -> {
|
||||||
assertEquals(genericOverlayInsetsRect1,
|
assertEquals(genericOverlayInsetsRect1,
|
||||||
window.getInsetsState().peekSource(sourceId1).getFrame());
|
window.getInsetsState().peekSource(sourceId1).getFrame());
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
rootTask.addLocalInsetsFrameProvider(provider2);
|
rootTask.addLocalInsetsFrameProvider(provider2, owner);
|
||||||
|
|
||||||
activity0.forAllWindows(window -> {
|
activity0.forAllWindows(window -> {
|
||||||
assertEquals(genericOverlayInsetsRect2,
|
assertEquals(genericOverlayInsetsRect2,
|
||||||
@@ -1520,7 +1533,7 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveLocalInsetsSourceProvider() {
|
public void testRemoveLocalInsetsFrameProvider() {
|
||||||
/*
|
/*
|
||||||
___ rootTask _______________________________________________
|
___ rootTask _______________________________________________
|
||||||
| | | |
|
| | | |
|
||||||
@@ -1554,21 +1567,22 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
|
|
||||||
activity2.addWindow(createWindowState(attrs2, activity2));
|
activity2.addWindow(createWindowState(attrs2, activity2));
|
||||||
|
|
||||||
|
final Binder owner = new Binder();
|
||||||
final Rect navigationBarInsetsRect1 = new Rect(0, 200, 1080, 700);
|
final Rect navigationBarInsetsRect1 = new Rect(0, 200, 1080, 700);
|
||||||
final Rect navigationBarInsetsRect2 = new Rect(0, 0, 1080, 200);
|
final Rect navigationBarInsetsRect2 = new Rect(0, 0, 1080, 200);
|
||||||
final InsetsFrameProvider provider1 =
|
final InsetsFrameProvider provider1 =
|
||||||
new InsetsFrameProvider(null, 1, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 1, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(navigationBarInsetsRect1);
|
.setArbitraryRectangle(navigationBarInsetsRect1);
|
||||||
final InsetsFrameProvider provider2 =
|
final InsetsFrameProvider provider2 =
|
||||||
new InsetsFrameProvider(null, 2, WindowInsets.Type.systemOverlays())
|
new InsetsFrameProvider(owner, 2, WindowInsets.Type.systemOverlays())
|
||||||
.setArbitraryRectangle(navigationBarInsetsRect2);
|
.setArbitraryRectangle(navigationBarInsetsRect2);
|
||||||
final int sourceId1 = provider1.getId();
|
final int sourceId1 = provider1.getId();
|
||||||
final int sourceId2 = provider2.getId();
|
final int sourceId2 = provider2.getId();
|
||||||
|
|
||||||
rootTask.addLocalInsetsFrameProvider(provider1);
|
rootTask.addLocalInsetsFrameProvider(provider1, owner);
|
||||||
container.addLocalInsetsFrameProvider(provider2);
|
container.addLocalInsetsFrameProvider(provider2, owner);
|
||||||
mDisplayContent.getInsetsStateController().onPostLayout();
|
mDisplayContent.getInsetsStateController().onPostLayout();
|
||||||
rootTask.removeLocalInsetsFrameProvider(provider1);
|
rootTask.removeLocalInsetsFrameProvider(provider1, owner);
|
||||||
mDisplayContent.getInsetsStateController().onPostLayout();
|
mDisplayContent.getInsetsStateController().onPostLayout();
|
||||||
|
|
||||||
activity0.forAllWindows(window -> {
|
activity0.forAllWindows(window -> {
|
||||||
@@ -1593,6 +1607,67 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddLocalInsetsFrameProvider_ownerDiesAfterAdding() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
|
final TestBinder owner = new TestBinder();
|
||||||
|
final InsetsFrameProvider provider =
|
||||||
|
new InsetsFrameProvider(owner, 0, WindowInsets.Type.systemOverlays())
|
||||||
|
.setArbitraryRectangle(new Rect());
|
||||||
|
task.addLocalInsetsFrameProvider(provider, owner);
|
||||||
|
|
||||||
|
assertTrue("The death recipient must exist.", owner.hasDeathRecipient());
|
||||||
|
assertTrue("The source must be added.", hasLocalSource(task, provider.getId()));
|
||||||
|
|
||||||
|
// The owner dies after adding the source.
|
||||||
|
owner.die();
|
||||||
|
|
||||||
|
assertFalse("The death recipient must be removed.", owner.hasDeathRecipient());
|
||||||
|
assertFalse("The source must be removed.", hasLocalSource(task, provider.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddLocalInsetsFrameProvider_ownerDiesBeforeAdding() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
|
final TestBinder owner = new TestBinder();
|
||||||
|
|
||||||
|
// The owner dies before adding the source.
|
||||||
|
owner.die();
|
||||||
|
|
||||||
|
final InsetsFrameProvider provider =
|
||||||
|
new InsetsFrameProvider(owner, 0, WindowInsets.Type.systemOverlays())
|
||||||
|
.setArbitraryRectangle(new Rect());
|
||||||
|
task.addLocalInsetsFrameProvider(provider, owner);
|
||||||
|
|
||||||
|
assertFalse("The death recipient must not exist.", owner.hasDeathRecipient());
|
||||||
|
assertFalse("The source must not be added.", hasLocalSource(task, provider.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveLocalInsetsFrameProvider_removeDeathRecipient() {
|
||||||
|
final Task task = createTask(mDisplayContent);
|
||||||
|
final TestBinder owner = new TestBinder();
|
||||||
|
final InsetsFrameProvider provider =
|
||||||
|
new InsetsFrameProvider(owner, 0, WindowInsets.Type.systemOverlays())
|
||||||
|
.setArbitraryRectangle(new Rect());
|
||||||
|
task.addLocalInsetsFrameProvider(provider, owner);
|
||||||
|
|
||||||
|
assertTrue("The death recipient must exist.", owner.hasDeathRecipient());
|
||||||
|
assertTrue("The source must be added.", hasLocalSource(task, provider.getId()));
|
||||||
|
|
||||||
|
task.removeLocalInsetsFrameProvider(provider, owner);
|
||||||
|
|
||||||
|
assertFalse("The death recipient must be removed.", owner.hasDeathRecipient());
|
||||||
|
assertFalse("The source must be removed.", hasLocalSource(task, provider.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasLocalSource(WindowContainer container, int sourceId) {
|
||||||
|
if (container.mLocalInsetsSources == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return container.mLocalInsetsSources.contains(sourceId);
|
||||||
|
}
|
||||||
|
|
||||||
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
|
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
|
||||||
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
|
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
|
||||||
private final int mLayer;
|
private final int mLayer;
|
||||||
@@ -1797,4 +1872,82 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
mIsVisibleRequested = isVisibleRequested;
|
mIsVisibleRequested = isVisibleRequested;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TestBinder implements IBinder {
|
||||||
|
|
||||||
|
private boolean mDead;
|
||||||
|
private final ArrayList<IBinder.DeathRecipient> mDeathRecipients = new ArrayList<>();
|
||||||
|
|
||||||
|
public void die() {
|
||||||
|
mDead = true;
|
||||||
|
for (int i = mDeathRecipients.size() - 1; i >= 0; i--) {
|
||||||
|
final DeathRecipient recipient = mDeathRecipients.get(i);
|
||||||
|
recipient.binderDied(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasDeathRecipient() {
|
||||||
|
return !mDeathRecipients.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void linkToDeath(@NonNull DeathRecipient recipient, int flags)
|
||||||
|
throws RemoteException {
|
||||||
|
if (mDead) {
|
||||||
|
throw new DeadObjectException();
|
||||||
|
}
|
||||||
|
mDeathRecipients.add(recipient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags) {
|
||||||
|
final boolean successes = mDeathRecipients.remove(recipient);
|
||||||
|
if (successes || mDead) {
|
||||||
|
return successes;
|
||||||
|
}
|
||||||
|
throw new NoSuchElementException("Given recipient has not been registered.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBinderAlive() {
|
||||||
|
return !mDead;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean pingBinder() {
|
||||||
|
return !mDead;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getInterfaceDescriptor() throws RemoteException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IInterface queryLocalInterface(@NonNull String descriptor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dump(@NonNull FileDescriptor fd, @Nullable String[] args)
|
||||||
|
throws RemoteException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dumpAsync(@NonNull FileDescriptor fd, @Nullable String[] args)
|
||||||
|
throws RemoteException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
|
||||||
|
@Nullable FileDescriptor err, @NonNull String[] args,
|
||||||
|
@Nullable ShellCallback shellCallback,
|
||||||
|
@NonNull ResultReceiver resultReceiver) throws RemoteException { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
|
||||||
|
throws RemoteException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user