Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Fix new lint from android 14 upgrade, and remove it from the baseline #47817

Merged
merged 15 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.os.Build;
import android.view.HapticFeedbackConstants;
import android.view.SoundEffectConstants;
Expand All @@ -25,6 +26,7 @@
import io.flutter.Log;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;

/** Android implementation of the platform plugin. */
Expand Down Expand Up @@ -512,14 +514,21 @@ private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat for

if (!clipboard.hasPrimaryClip()) return null;

CharSequence charSequence = null;
try {
ClipData clip = clipboard.getPrimaryClip();
if (clip == null) return null;
if (format == null || format == PlatformChannel.ClipboardContentFormat.PLAIN_TEXT) {
ClipData.Item item = clip.getItemAt(0);
AssetFileDescriptor assetFileDescriptor = null;
if (item.getUri() != null)
activity.getContentResolver().openTypedAssetFileDescriptor(item.getUri(), "text/*", null);
return item.coerceToText(activity);
assetFileDescriptor =
activity
.getContentResolver()
.openTypedAssetFileDescriptor(item.getUri(), "text/*", null);
charSequence = item.coerceToText(activity);
if (assetFileDescriptor != null) assetFileDescriptor.close();
return charSequence;
}
} catch (SecurityException e) {
Log.w(
Expand All @@ -531,6 +540,9 @@ private CharSequence getClipboardData(PlatformChannel.ClipboardContentFormat for
return null;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
Log.w(TAG, "Failed to close AssetFileDescriptor while accessing clipboard data.", e);
return charSequence;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
Expand All @@ -20,9 +24,11 @@

import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.Build;
import android.view.View;
Expand Down Expand Up @@ -84,18 +90,39 @@ public void platformPlugin_getClipboardData() throws IOException {
PlatformChannel fakePlatformChannel = mock(PlatformChannel.class);
PlatformPlugin platformPlugin = new PlatformPlugin(fakeActivity, fakePlatformChannel);

// Successfully get the contents of the primary clip when they contain text.
ClipboardContentFormat clipboardFormat = ClipboardContentFormat.PLAIN_TEXT;
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
ClipData clip = ClipData.newPlainText("label", "Text");
clipboardManager.setPrimaryClip(clip);
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));

ContentResolver contentResolver = ctx.getContentResolver();
// Return null when the primary clip contains non-text media.
ContentResolver contentResolver = spy(ctx.getContentResolver());
when(fakeActivity.getContentResolver()).thenReturn(contentResolver);
Uri uri = Uri.parse("content://media/external_primary/images/media/");
clip = ClipData.newUri(contentResolver, "URI", uri);
clipboardManager.setPrimaryClip(clip);
assertNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));

// Still return text when the AssetFileDescriptor throws an IOException.
when(fakeActivity.getContentResolver()).thenReturn(contentResolver);
ClipDescription clipDescription =
new ClipDescription(
"label",
new String[] {
ClipDescription.MIMETYPE_TEXT_PLAIN, ClipDescription.MIMETYPE_TEXT_URILIST
});
ClipData.Item clipDataItem = new ClipData.Item("Text", null, uri);
ClipData clipData = new ClipData(clipDescription, clipDataItem);
clipboardManager.setPrimaryClip(clipData);
AssetFileDescriptor fakeAssetFileDescriptor = mock(AssetFileDescriptor.class);
doReturn(fakeAssetFileDescriptor)
.when(contentResolver)
.openTypedAssetFileDescriptor(eq(uri), anyString(), eq(null));
doThrow(new IOException()).when(fakeAssetFileDescriptor).close();
assertNotNull(platformPlugin.mPlatformMessageHandler.getClipboardData(clipboardFormat));
verify(fakeAssetFileDescriptor).close();
}

@SuppressWarnings("deprecation")
Expand Down
11 changes: 0 additions & 11 deletions tools/android_lint/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,6 @@
column="82"/>
</issue>

<issue
id="Recycle"
message="This `AssetFileDescriptor` should be freed up after use with `#close()`"
errorLine1=" activity.getContentResolver().openTypedAssetFileDescriptor(item.getUri(), &quot;text/*&quot;, null);"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java"
line="522"
column="41"/>
</issue>

<issue
id="ClickableViewAccessibility"
message="Custom view `FlutterView` overrides `onTouchEvent` but not `performClick`"
Expand Down