Loading core/java/android/content/ClipData.java +29 −3 Original line number Diff line number Diff line Loading @@ -179,6 +179,10 @@ public class ClipData implements Parcelable { final ArrayList<Item> mItems; // This is false by default unless the ClipData is obtained via // {@link #copyForTransferWithActivityInfo}. private boolean mParcelItemActivityInfos; /** * Description of a single item in a ClipData. * Loading @@ -204,9 +208,11 @@ public class ClipData implements Parcelable { final Intent mIntent; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) Uri mUri; // Additional activity info resolved by the system ActivityInfo mActivityInfo; private TextLinks mTextLinks; // Additional activity info resolved by the system. This is only parceled with the ClipData // if the data is obtained from {@link #copyForTransferWithActivityInfo} private ActivityInfo mActivityInfo; /** @hide */ public Item(Item other) { Loading @@ -214,6 +220,8 @@ public class ClipData implements Parcelable { mHtmlText = other.mHtmlText; mIntent = other.mIntent; mUri = other.mUri; mActivityInfo = other.mActivityInfo; mTextLinks = other.mTextLinks; } /** Loading Loading @@ -816,6 +824,24 @@ public class ClipData implements Parcelable { mItems = new ArrayList<Item>(other.mItems); } /** * Returns a copy of the ClipData which will parcel the Item's activity infos. * @hide */ public ClipData copyForTransferWithActivityInfo() { ClipData copy = new ClipData(this); copy.mParcelItemActivityInfos = true; return copy; } /** * Returns whether this clip data will parcel the Item's activity infos. * @hide */ public boolean willParcelWithActivityInfo() { return mParcelItemActivityInfos; } /** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. Loading Loading @@ -1208,7 +1234,7 @@ public class ClipData implements Parcelable { dest.writeString8(item.mHtmlText); dest.writeTypedObject(item.mIntent, flags); dest.writeTypedObject(item.mUri, flags); dest.writeTypedObject(item.mActivityInfo, flags); dest.writeTypedObject(mParcelItemActivityInfos ? item.mActivityInfo : null, flags); dest.writeTypedObject(item.mTextLinks, flags); } } Loading services/core/java/com/android/server/wm/DragState.java +7 −5 Original line number Diff line number Diff line Loading @@ -316,7 +316,7 @@ class DragState { final int myPid = Process.myPid(); final IBinder clientToken = touchedWin.mClient.asBinder(); final DragEvent event = obtainDragEvent(DragEvent.ACTION_DROP, x, y, true /* includeData */, targetInterceptsGlobalDrag(touchedWin), mData, targetInterceptsGlobalDrag(touchedWin), dragAndDropPermissions); try { touchedWin.mClient.dispatchDragEvent(event); Loading Loading @@ -462,8 +462,10 @@ class DragState { boolean containsAppExtras) { final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin); if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) { // Only allow the extras to be dispatched to a global-intercepting drag target ClipData data = interceptsGlobalDrag ? mData.copyForTransferWithActivityInfo() : null; DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY, interceptsGlobalDrag, false /* includeDragSurface */, data, false /* includeDragSurface */, null /* dragAndDropPermission */); try { newWin.mClient.dispatchDragEvent(event); Loading Loading @@ -614,11 +616,11 @@ class DragState { return mDragInProgress; } private DragEvent obtainDragEvent(int action, float x, float y, boolean includeData, private DragEvent obtainDragEvent(int action, float x, float y, ClipData data, boolean includeDragSurface, IDragAndDropPermissions dragAndDropPermissions) { return DragEvent.obtain(action, x, y, mThumbOffsetX, mThumbOffsetY, null /* localState */, mDataDescription, includeData ? mData : null, includeDragSurface ? mSurfaceControl : null, null /* localState */, mDataDescription, data, includeDragSurface ? mSurfaceControl : null, dragAndDropPermissions, false /* result */); } Loading services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java +23 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.DragEvent.ACTION_DRAG_STARTED; import static android.view.DragEvent.ACTION_DROP; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; Loading @@ -31,7 +32,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.eq; Loading Loading @@ -267,12 +270,32 @@ public class DragDropControllerTests extends WindowTestsBase { assertTrue(globalInterceptWindowDragEvents.get(0).getAction() == ACTION_DRAG_STARTED); // Verify that only the global intercept window receives the clip data with the // resolved activity info for the drag assertNull(localWindowDragEvents.get(0).getClipData()); assertTrue(globalInterceptWindowDragEvents.get(0).getClipData() .willParcelWithActivityInfo()); mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0); mTarget.handleMotionEvent(false, 0, 0); mToken = globalInterceptWindow.mClient.asBinder(); // Verify the drop event is only sent for the global intercept window assertTrue(nonLocalWindowDragEvents.isEmpty()); assertTrue(last(localWindowDragEvents).getAction() != ACTION_DROP); assertTrue(last(globalInterceptWindowDragEvents).getAction() == ACTION_DROP); // Verify that item extras were not sent with the drop event assertNull(last(localWindowDragEvents).getClipData()); assertFalse(last(globalInterceptWindowDragEvents).getClipData() .willParcelWithActivityInfo()); }); } private DragEvent last(ArrayList<DragEvent> list) { return list.get(list.size() - 1); } @Test public void testValidateAppActivityArguments() { final Session session = new Session(mWm, new IWindowSessionCallback.Stub() { Loading Loading
core/java/android/content/ClipData.java +29 −3 Original line number Diff line number Diff line Loading @@ -179,6 +179,10 @@ public class ClipData implements Parcelable { final ArrayList<Item> mItems; // This is false by default unless the ClipData is obtained via // {@link #copyForTransferWithActivityInfo}. private boolean mParcelItemActivityInfos; /** * Description of a single item in a ClipData. * Loading @@ -204,9 +208,11 @@ public class ClipData implements Parcelable { final Intent mIntent; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) Uri mUri; // Additional activity info resolved by the system ActivityInfo mActivityInfo; private TextLinks mTextLinks; // Additional activity info resolved by the system. This is only parceled with the ClipData // if the data is obtained from {@link #copyForTransferWithActivityInfo} private ActivityInfo mActivityInfo; /** @hide */ public Item(Item other) { Loading @@ -214,6 +220,8 @@ public class ClipData implements Parcelable { mHtmlText = other.mHtmlText; mIntent = other.mIntent; mUri = other.mUri; mActivityInfo = other.mActivityInfo; mTextLinks = other.mTextLinks; } /** Loading Loading @@ -816,6 +824,24 @@ public class ClipData implements Parcelable { mItems = new ArrayList<Item>(other.mItems); } /** * Returns a copy of the ClipData which will parcel the Item's activity infos. * @hide */ public ClipData copyForTransferWithActivityInfo() { ClipData copy = new ClipData(this); copy.mParcelItemActivityInfos = true; return copy; } /** * Returns whether this clip data will parcel the Item's activity infos. * @hide */ public boolean willParcelWithActivityInfo() { return mParcelItemActivityInfos; } /** * Create a new ClipData holding data of the type * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}. Loading Loading @@ -1208,7 +1234,7 @@ public class ClipData implements Parcelable { dest.writeString8(item.mHtmlText); dest.writeTypedObject(item.mIntent, flags); dest.writeTypedObject(item.mUri, flags); dest.writeTypedObject(item.mActivityInfo, flags); dest.writeTypedObject(mParcelItemActivityInfos ? item.mActivityInfo : null, flags); dest.writeTypedObject(item.mTextLinks, flags); } } Loading
services/core/java/com/android/server/wm/DragState.java +7 −5 Original line number Diff line number Diff line Loading @@ -316,7 +316,7 @@ class DragState { final int myPid = Process.myPid(); final IBinder clientToken = touchedWin.mClient.asBinder(); final DragEvent event = obtainDragEvent(DragEvent.ACTION_DROP, x, y, true /* includeData */, targetInterceptsGlobalDrag(touchedWin), mData, targetInterceptsGlobalDrag(touchedWin), dragAndDropPermissions); try { touchedWin.mClient.dispatchDragEvent(event); Loading Loading @@ -462,8 +462,10 @@ class DragState { boolean containsAppExtras) { final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin); if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) { // Only allow the extras to be dispatched to a global-intercepting drag target ClipData data = interceptsGlobalDrag ? mData.copyForTransferWithActivityInfo() : null; DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY, interceptsGlobalDrag, false /* includeDragSurface */, data, false /* includeDragSurface */, null /* dragAndDropPermission */); try { newWin.mClient.dispatchDragEvent(event); Loading Loading @@ -614,11 +616,11 @@ class DragState { return mDragInProgress; } private DragEvent obtainDragEvent(int action, float x, float y, boolean includeData, private DragEvent obtainDragEvent(int action, float x, float y, ClipData data, boolean includeDragSurface, IDragAndDropPermissions dragAndDropPermissions) { return DragEvent.obtain(action, x, y, mThumbOffsetX, mThumbOffsetY, null /* localState */, mDataDescription, includeData ? mData : null, includeDragSurface ? mSurfaceControl : null, null /* localState */, mDataDescription, data, includeDragSurface ? mSurfaceControl : null, dragAndDropPermissions, false /* result */); } Loading
services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java +23 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.DragEvent.ACTION_DRAG_STARTED; import static android.view.DragEvent.ACTION_DROP; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; Loading @@ -31,7 +32,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.eq; Loading Loading @@ -267,12 +270,32 @@ public class DragDropControllerTests extends WindowTestsBase { assertTrue(globalInterceptWindowDragEvents.get(0).getAction() == ACTION_DRAG_STARTED); // Verify that only the global intercept window receives the clip data with the // resolved activity info for the drag assertNull(localWindowDragEvents.get(0).getClipData()); assertTrue(globalInterceptWindowDragEvents.get(0).getClipData() .willParcelWithActivityInfo()); mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0); mTarget.handleMotionEvent(false, 0, 0); mToken = globalInterceptWindow.mClient.asBinder(); // Verify the drop event is only sent for the global intercept window assertTrue(nonLocalWindowDragEvents.isEmpty()); assertTrue(last(localWindowDragEvents).getAction() != ACTION_DROP); assertTrue(last(globalInterceptWindowDragEvents).getAction() == ACTION_DROP); // Verify that item extras were not sent with the drop event assertNull(last(localWindowDragEvents).getClipData()); assertFalse(last(globalInterceptWindowDragEvents).getClipData() .willParcelWithActivityInfo()); }); } private DragEvent last(ArrayList<DragEvent> list) { return list.get(list.size() - 1); } @Test public void testValidateAppActivityArguments() { final Session session = new Session(mWm, new IWindowSessionCallback.Stub() { Loading