Merge "Fix MIME type of non-plain text share intents" into tm-qpr-dev

This commit is contained in:
Matt Casey
2022-09-19 21:22:48 +00:00
committed by Android (Google) Code Review
3 changed files with 227 additions and 43 deletions

View File

@@ -119,15 +119,12 @@ import java.util.ArrayList;
*/
public class ClipboardOverlayController {
private static final String TAG = "ClipboardOverlayCtrlr";
private static final String REMOTE_COPY_ACTION = "android.intent.action.REMOTE_COPY";
/** Constants for screenshot/copy deconflicting */
public static final String SCREENSHOT_ACTION = "com.android.systemui.SCREENSHOT";
public static final String SELF_PERMISSION = "com.android.systemui.permission.SELF";
public static final String COPY_OVERLAY_ACTION = "com.android.systemui.COPY";
private static final String EXTRA_EDIT_SOURCE_CLIPBOARD = "edit_source_clipboard";
private static final int CLIPBOARD_DEFAULT_TIMEOUT_MILLIS = 6000;
private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
private static final int FONT_SEARCH_STEP_PX = 4;
@@ -383,7 +380,7 @@ public class ClipboardOverlayController {
mTextPreview);
accessibilityAnnouncement = mContext.getString(R.string.clipboard_content_copied);
}
Intent remoteCopyIntent = getRemoteCopyIntent(clipData);
Intent remoteCopyIntent = IntentCreator.getRemoteCopyIntent(clipData, mContext);
// Only show remote copy if it's available.
PackageManager packageManager = mContext.getPackageManager();
if (packageManager.resolveActivity(
@@ -500,41 +497,19 @@ public class ClipboardOverlayController {
private void editImage(Uri uri) {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
String editorPackage = mContext.getString(R.string.config_screenshotEditor);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
editIntent.setDataAndType(uri, "image/*");
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
editIntent.putExtra(EXTRA_EDIT_SOURCE_CLIPBOARD, true);
mContext.startActivity(editIntent);
mContext.startActivity(IntentCreator.getImageEditIntent(uri, mContext));
animateOut();
}
private void editText() {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_EDIT_TAPPED);
Intent editIntent = new Intent(mContext, EditTextActivity.class);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(editIntent);
mContext.startActivity(IntentCreator.getTextEditorIntent(mContext));
animateOut();
}
private void shareContent(ClipData clip) {
mClipboardLogger.logSessionComplete(CLIPBOARD_OVERLAY_SHARE_TAPPED);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setDataAndType(
clip.getItemAt(0).getUri(), clip.getDescription().getMimeType(0));
shareIntent.putExtra(Intent.EXTRA_TEXT, clip.getItemAt(0).getText().toString());
if (clip.getItemAt(0).getUri() != null) {
shareIntent.putExtra(Intent.EXTRA_STREAM, clip.getItemAt(0).getUri());
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
Intent chooserIntent = Intent.createChooser(shareIntent, null)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
mContext.startActivity(chooserIntent);
mContext.startActivity(IntentCreator.getShareIntent(clip, mContext));
animateOut();
}
@@ -667,20 +642,6 @@ public class ClipboardOverlayController {
mContext.getString(R.string.clipboard_edit), null);
}
private Intent getRemoteCopyIntent(ClipData clipData) {
Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
String remoteCopyPackage = mContext.getString(R.string.config_remoteCopyPackage);
if (!TextUtils.isEmpty(remoteCopyPackage)) {
nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
}
nearbyIntent.setClipData(clipData);
nearbyIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return nearbyIntent;
}
private void animateIn() {
if (mAccessibilityManager.isEnabled()) {
mDismissButton.setVisibility(View.VISIBLE);

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.clipboardoverlay;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import com.android.systemui.R;
class IntentCreator {
private static final String EXTRA_EDIT_SOURCE_CLIPBOARD = "edit_source_clipboard";
private static final String REMOTE_COPY_ACTION = "android.intent.action.REMOTE_COPY";
static Intent getTextEditorIntent(Context context) {
Intent intent = new Intent(context, EditTextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent;
}
static Intent getShareIntent(ClipData clipData, Context context) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
// From the ACTION_SEND docs:
// "If using EXTRA_TEXT, the MIME type should be "text/plain"; otherwise it should be the
// MIME type of the data in EXTRA_STREAM"
if (clipData.getItemAt(0).getUri() != null) {
shareIntent.setDataAndType(
clipData.getItemAt(0).getUri(), clipData.getDescription().getMimeType(0));
shareIntent.putExtra(Intent.EXTRA_STREAM, clipData.getItemAt(0).getUri());
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
shareIntent.putExtra(Intent.EXTRA_TEXT, clipData.getItemAt(0).coerceToText(context));
shareIntent.setType("text/plain");
}
Intent chooserIntent = Intent.createChooser(shareIntent, null)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
return chooserIntent;
}
static Intent getImageEditIntent(Uri uri, Context context) {
String editorPackage = context.getString(R.string.config_screenshotEditor);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
editIntent.setDataAndType(uri, "image/*");
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
editIntent.putExtra(EXTRA_EDIT_SOURCE_CLIPBOARD, true);
return editIntent;
}
static Intent getRemoteCopyIntent(ClipData clipData, Context context) {
Intent nearbyIntent = new Intent(REMOTE_COPY_ACTION);
String remoteCopyPackage = context.getString(R.string.config_remoteCopyPackage);
if (!TextUtils.isEmpty(remoteCopyPackage)) {
nearbyIntent.setComponent(ComponentName.unflattenFromString(remoteCopyPackage));
}
nearbyIntent.setClipData(clipData);
nearbyIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
nearbyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return nearbyIntent;
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.clipboardoverlay;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.Intent;
import android.net.Uri;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class IntentCreatorTest extends SysuiTestCase {
private static final int EXTERNAL_INTENT_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION;
@Test
public void test_getTextEditorIntent() {
Intent intent = IntentCreator.getTextEditorIntent(getContext());
assertEquals(new ComponentName(getContext(), EditTextActivity.class),
intent.getComponent());
assertFlags(intent, Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
}
@Test
public void test_getRemoteCopyIntent() {
getContext().getOrCreateTestableResources().addOverride(R.string.config_remoteCopyPackage,
"");
ClipData clipData = ClipData.newPlainText("Test", "Test Item");
Intent intent = IntentCreator.getRemoteCopyIntent(clipData, getContext());
assertEquals(null, intent.getComponent());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
assertEquals(clipData, intent.getClipData());
// Try again with a remote copy component
ComponentName fakeComponent = new ComponentName("com.android.remotecopy",
"com.android.remotecopy.RemoteCopyActivity");
getContext().getOrCreateTestableResources().addOverride(R.string.config_remoteCopyPackage,
fakeComponent.flattenToString());
intent = IntentCreator.getRemoteCopyIntent(clipData, getContext());
assertEquals(fakeComponent, intent.getComponent());
}
@Test
public void test_getImageEditIntent() {
getContext().getOrCreateTestableResources().addOverride(R.string.config_screenshotEditor,
"");
Uri fakeUri = Uri.parse("content://foo");
Intent intent = IntentCreator.getImageEditIntent(fakeUri, getContext());
assertEquals(Intent.ACTION_EDIT, intent.getAction());
assertEquals("image/*", intent.getType());
assertEquals(null, intent.getComponent());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
// try again with an editor component
ComponentName fakeComponent = new ComponentName("com.android.remotecopy",
"com.android.remotecopy.RemoteCopyActivity");
getContext().getOrCreateTestableResources().addOverride(R.string.config_screenshotEditor,
fakeComponent.flattenToString());
intent = IntentCreator.getImageEditIntent(fakeUri, getContext());
assertEquals(fakeComponent, intent.getComponent());
}
@Test
public void test_getShareIntent_plaintext() {
ClipData clipData = ClipData.newPlainText("Test", "Test Item");
Intent intent = IntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
assertEquals("Test Item", target.getStringExtra(Intent.EXTRA_TEXT));
assertEquals("text/plain", target.getType());
}
@Test
public void test_getShareIntent_html() {
ClipData clipData = ClipData.newHtmlText("Test", "Some HTML",
"<b>Some HTML</b>");
Intent intent = IntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
assertEquals("Some HTML", target.getStringExtra(Intent.EXTRA_TEXT));
assertEquals("text/plain", target.getType());
}
@Test
public void test_getShareIntent_image() {
Uri uri = Uri.parse("content://something");
ClipData clipData = new ClipData("Test", new String[]{"image/png"},
new ClipData.Item(uri));
Intent intent = IntentCreator.getShareIntent(clipData, getContext());
assertEquals(Intent.ACTION_CHOOSER, intent.getAction());
assertFlags(intent, EXTERNAL_INTENT_FLAGS);
Intent target = intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent.class);
assertEquals(uri, target.getData());
assertEquals("image/png", target.getType());
}
// Assert that the given flags are set
private void assertFlags(Intent intent, int flags) {
assertTrue((intent.getFlags() & flags) == flags);
}
}