Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
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
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -44329,6 +44329,7 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/syst
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/ProcessTextChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/RestorationChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/ScribeChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SensitiveContentChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SystemChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/common/ActivityLifecycleListener.java + ../../../flutter/LICENSE
Expand All @@ -44353,6 +44354,7 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/ImeSyn
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/ListenableEditingState.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/ScribePlugin.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/view/SensitiveContentPlugin.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/TextEditingDelta.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java + ../../../flutter/LICENSE
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ android_java_sources = [
"io/flutter/embedding/engine/systemchannels/ProcessTextChannel.java",
"io/flutter/embedding/engine/systemchannels/RestorationChannel.java",
"io/flutter/embedding/engine/systemchannels/ScribeChannel.java",
"io/flutter/embedding/engine/systemchannels/SensitiveContentChannel.java",
"io/flutter/embedding/engine/systemchannels/SettingsChannel.java",
"io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java",
"io/flutter/embedding/engine/systemchannels/SystemChannel.java",
Expand Down Expand Up @@ -338,6 +339,7 @@ android_java_sources = [
"io/flutter/plugin/platform/VirtualDisplayController.java",
"io/flutter/plugin/platform/WindowManagerHandler.java",
"io/flutter/plugin/text/ProcessTextPlugin.java",
"io/flutter/plugin/view/SensitiveContentPlugin.java",
"io/flutter/util/HandlerCompat.java",
"io/flutter/util/PathUtils.java",
"io/flutter/util/Preconditions.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.plugin.view.SensitiveContentPlugin;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -220,7 +221,7 @@ public class FlutterActivity extends Activity
* <p>This ID can be used to lookup {@code FlutterView} in the Android view hierarchy. For more,
* see {@link android.view.View#findViewById}.
*/
public static final int FLUTTER_VIEW_ID = View.generateViewId();
public static final int FLUTTER_VIEW_ID = 0;

/**
* Creates an {@link Intent} that launches a {@code FlutterActivity}, which creates a {@link
Expand Down Expand Up @@ -1312,6 +1313,13 @@ public PlatformPlugin providePlatformPlugin(
return new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel(), this);
}

@Nullable
@Override
public SensitiveContentPlugin provideSensitiveContentPlugin(
@Nullable Activity activity, @NonNull FlutterEngine flutterEngine) {
return new SensitiveContentPlugin(getActivity(), flutterEngine.getSensitiveContentChannel());
}

/**
* Hook for subclasses to easily configure a {@code FlutterEngine}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.plugin.view.SensitiveContentPlugin;
import java.util.Arrays;
import java.util.List;

Expand Down Expand Up @@ -89,6 +90,7 @@ public interface DelegateFactory {
@Nullable private FlutterEngine flutterEngine;
@VisibleForTesting @Nullable FlutterView flutterView;
@Nullable private PlatformPlugin platformPlugin;
@Nullable private SensitiveContentPlugin sensitiveContentPlugin;
@VisibleForTesting @Nullable OnPreDrawListener activePreDrawListener;
private boolean isFlutterEngineFromHost;
private boolean isFlutterUiDisplayed;
Expand Down Expand Up @@ -140,6 +142,7 @@ void release() {
this.flutterEngine = null;
this.flutterView = null;
this.platformPlugin = null;
this.sensitiveContentPlugin = null;
}

/**
Expand Down Expand Up @@ -215,6 +218,7 @@ void onAttach(@NonNull Context context) {
// control of the entire window. This is unacceptable for non-fullscreen
// use-cases.
platformPlugin = host.providePlatformPlugin(host.getActivity(), flutterEngine);
sensitiveContentPlugin = host.provideSensitiveContentPlugin(host.getActivity(), flutterEngine);

host.configureFlutterEngine(flutterEngine);
isAttached = true;
Expand Down Expand Up @@ -756,6 +760,11 @@ void onDetach() {
platformPlugin = null;
}

if (sensitiveContentPlugin != null) {
sensitiveContentPlugin.destroy();
sensitiveContentPlugin = null;
}

if (host.shouldDispatchAppLifecycleState() && flutterEngine != null) {
flutterEngine.getLifecycleChannel().appIsDetached();
}
Expand Down Expand Up @@ -1184,6 +1193,14 @@ private void ensureAlive() {
PlatformPlugin providePlatformPlugin(
@Nullable Activity activity, @NonNull FlutterEngine flutterEngine);

/**
* Hook for host to create/provide a {@link SensitiveContentPlugin} if the associated Flutter
* experience should set content sensitivity.
*/
@Nullable
SensitiveContentPlugin provideSensitiveContentPlugin(
@Nullable Activity activity, @NonNull FlutterEngine flutterEngine);

/**
* Hook for the host to configure the {@link io.flutter.embedding.engine.FlutterEngine} as
* desired.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import io.flutter.embedding.engine.FlutterShellArgs;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.plugin.platform.PlatformPlugin;
import io.flutter.plugin.view.SensitiveContentPlugin;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -104,7 +105,8 @@ public class FlutterFragment extends Fragment
* <p>This ID can be used to lookup {@code FlutterView} in the Android view hierarchy. For more,
* see {@link android.view.View#findViewById}.
*/
public static final int FLUTTER_VIEW_ID = View.generateViewId();
// TODO(camsim99): Determine if we should involve FlutterFragment.
public static final int FLUTTER_VIEW_ID = 1;

private static final String TAG = "FlutterFragment";

Expand Down Expand Up @@ -1501,6 +1503,17 @@ public PlatformPlugin providePlatformPlugin(
}
}

@Nullable
@Override
public SensitiveContentPlugin provideSensitiveContentPlugin(
@Nullable Activity activity, @NonNull FlutterEngine flutterEngine) {
if (activity != null) {
return new SensitiveContentPlugin(getActivity(), flutterEngine.getSensitiveContentChannel());
} else {
return null;
}
}

/**
* Configures a {@link io.flutter.embedding.engine.FlutterEngine} after its creation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.flutter.embedding.engine.systemchannels.ProcessTextChannel;
import io.flutter.embedding.engine.systemchannels.RestorationChannel;
import io.flutter.embedding.engine.systemchannels.ScribeChannel;
import io.flutter.embedding.engine.systemchannels.SensitiveContentChannel;
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
import io.flutter.embedding.engine.systemchannels.SpellCheckChannel;
import io.flutter.embedding.engine.systemchannels.SystemChannel;
Expand Down Expand Up @@ -102,6 +103,7 @@ public class FlutterEngine implements ViewUtils.DisplayUpdater {
@NonNull private final PlatformChannel platformChannel;
@NonNull private final ProcessTextChannel processTextChannel;
@NonNull private final ScribeChannel scribeChannel;
@NonNull private final SensitiveContentChannel sensitiveContentChannel;
@NonNull private final SettingsChannel settingsChannel;
@NonNull private final SpellCheckChannel spellCheckChannel;
@NonNull private final SystemChannel systemChannel;
Expand Down Expand Up @@ -340,6 +342,7 @@ public FlutterEngine(
processTextChannel = new ProcessTextChannel(dartExecutor, context.getPackageManager());
restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
scribeChannel = new ScribeChannel(dartExecutor);
sensitiveContentChannel = new SensitiveContentChannel(dartExecutor);
settingsChannel = new SettingsChannel(dartExecutor);
spellCheckChannel = new SpellCheckChannel(dartExecutor);
systemChannel = new SystemChannel(dartExecutor);
Expand Down Expand Up @@ -619,6 +622,12 @@ public ScribeChannel getScribeChannel() {
return scribeChannel;
}

/** System channel that handles setting content sensitivity. */
@NonNull
public SensitiveContentChannel getSensitiveContentChannel() {
return sensitiveContentChannel;
}

/** System channel that sends and receives spell check requests and results. */
@NonNull
public SpellCheckChannel getSpellCheckChannel() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.embedding.engine.systemchannels;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.Log;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMethodCodec;
import java.util.ArrayList;

/**
* {@link SensitiveContentChannel} is a platform channel that is used by the framework to set the
* content sensitivity of native Flutter Android {@code View}s.
*/
public class SensitiveContentChannel {
private static final String TAG = "SensitiveContentChannel";

public final MethodChannel channel;
private SensitiveContentMethodHandler sensitiveContentMethodHandler;

@NonNull
public final MethodChannel.MethodCallHandler parsingMethodHandler =
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (sensitiveContentMethodHandler == null) {
Log.v(
TAG,
"No SensitiveContentChannel registered, call not forwarded to sensitive content API.");
return;
}
String method = call.method;
Object args = call.arguments;
Log.v(TAG, "Received '" + method + "' message.");
switch (method) {
case "SensitiveContent.setContentSensitivity":
final ArrayList<Object> argumentList = (ArrayList<Object>) args;
final int flutterViewId = (int) argumentList.get(0);
final int contentSensitivityLevel = (int) argumentList.get(1);
try {
sensitiveContentMethodHandler.setContentSensitivity(
flutterViewId, contentSensitivityLevel, result);
} catch (IllegalStateException exception) {
result.error("error", exception.getMessage(), null);
}
break;
default:
result.notImplemented();
break;
}
}
};

public SensitiveContentChannel(@NonNull DartExecutor dartExecutor) {
channel =
new MethodChannel(dartExecutor, "flutter/sensitivecontent", StandardMethodCodec.INSTANCE);
channel.setMethodCallHandler(parsingMethodHandler);
}

/**
* Sets the {@link SensitiveContentMethodHandler} which receives all requests to set a particular
* content sensitivty level sent through this channel.
*/
public void setSensitiveContentMethodHandler(
@Nullable SensitiveContentMethodHandler sensitiveContentMethodHandler) {
this.sensitiveContentMethodHandler = sensitiveContentMethodHandler;
}

public interface SensitiveContentMethodHandler {
/**
* Requests that content being marked with the requested {@code contentSensitivity} mode for the
* native Flutter Android {@code View} whose ID matches {@code flutterViewId}.
*/
void setContentSensitivity(
@NonNull int flutterViewId,
@NonNull int contentSensitivity,
@NonNull MethodChannel.Result result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugin.view;

import android.app.Activity;
import android.view.View;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.systemchannels.SensitiveContentChannel;
import io.flutter.plugin.common.MethodChannel;

/**
* {@link SensitiveContentPlugin} is the implementation of all functionality needed to set content
* sensitive on a native Flutter Android {@code View}.
*
* <p>The plugin handles requests for setting content sensitivity sent by the {@link
* io.flutter.embedding.engine.systemchannels.SensitiveContentChannel} via making a call to the
* relevant {@code View}.
*/
public class SensitiveContentPlugin
implements SensitiveContentChannel.SensitiveContentMethodHandler {

private final Activity mflutterActivity;
private final SensitiveContentChannel mSensitiveContentChannel;

public SensitiveContentPlugin(
@NonNull Activity flutterActivity, @NonNull SensitiveContentChannel sensitiveContentChannel) {
mflutterActivity = flutterActivity;
mSensitiveContentChannel = sensitiveContentChannel;

mSensitiveContentChannel.setSensitiveContentMethodHandler(this);
}

int i = 0;
/**
* Sets content sensitivity level of the Android {@code View} with the specified {@code
* flutterViewId} to the level specified by {@contentSensitivity}.
*/
@Override
public void setContentSensitivity(
@NonNull int flutterViewId,
@NonNull int contentSensitivity,
@NonNull MethodChannel.Result result) {
final View flutterView = mflutterActivity.findViewById(flutterViewId);
if (flutterView == null) {
result.error("error", "Requested Flutter View to set content sensitivty of not found.", null);
}

final int currentContentSensitivity = flutterView.getContentSensitivity();
flutterView.setContentSensitivity(contentSensitivity);

final boolean shouldInvalidateView =
currentContentSensitivity == View.CONTENT_SENSITIVITY_SENSITIVE
&& contentSensitivity != View.CONTENT_SENSITIVITY_SENSITIVE;
if (shouldInvalidateView) {
flutterView.invalidate();
}

result.success(null);
}

/**
* Releases all resources held by this {@code SensitiveContentPlugin}.
*
* <p>Do not invoke any methods on a {@code SensitiveContentPlugin} after invoking this method.
*/
public void destroy() {
this.mSensitiveContentChannel.setSensitiveContentMethodHandler(null);
}
}
Loading