diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 64a5e9b0cced1..0c22c91301648 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -251,6 +251,23 @@ embedding_dependencies_jars = ], "list lines") +action("check_imports") { + script = "//flutter/tools/android_illegal_imports.py" + + sources = android_java_sources + + stamp_file = "$root_out_dir/check_android_imports" + + # File does not actually get created, but GN expects us to have an output here. + outputs = [ stamp_file ] + + args = [ + "--stamp", + rebase_path(stamp_file), + "--files", + ] + rebase_path(android_java_sources) +} + action("flutter_shell_java") { script = "//build/android/gyp/javac.py" depfile = "$target_gen_dir/$target_name.d" @@ -299,7 +316,10 @@ action("flutter_shell_java") { args += rebase_path(sources, root_build_dir) - deps = [ ":gen_android_build_config_java" ] + deps = [ + ":check_imports", + ":gen_android_build_config_java", + ] } action("icudtl_object") { diff --git a/shell/platform/android/io/flutter/Log.java b/shell/platform/android/io/flutter/Log.java index 2fb8d029e79a5..fa31b8476a0f5 100644 --- a/shell/platform/android/io/flutter/Log.java +++ b/shell/platform/android/io/flutter/Log.java @@ -13,6 +13,13 @@ public class Log { private static int logLevel = android.util.Log.DEBUG; + public static int ASSERT = android.util.Log.ASSERT; + public static int DEBUG = android.util.Log.DEBUG; + public static int ERROR = android.util.Log.ERROR; + public static int INFO = android.util.Log.INFO; + public static int VERBOSE = android.util.Log.VERBOSE; + public static int WARN = android.util.Log.WARN; + /** * Sets a log cutoff such that a log level of lower priority than {@code logLevel} is filtered * out. @@ -23,6 +30,12 @@ public static void setLogLevel(int logLevel) { Log.logLevel = logLevel; } + public static void println(@NonNull int level, @NonNull String tag, @NonNull String message) { + if (BuildConfig.DEBUG && logLevel <= level) { + android.util.Log.println(level, tag, message); + } + } + public static void v(@NonNull String tag, @NonNull String message) { if (BuildConfig.DEBUG && logLevel <= android.util.Log.VERBOSE) { android.util.Log.v(tag, message); diff --git a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java index 970f09775a385..e337f373f7ebe 100644 --- a/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java +++ b/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java @@ -19,12 +19,12 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; +import io.flutter.Log; import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.platform.PlatformPlugin; import io.flutter.util.Preconditions; diff --git a/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java b/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java index 14d7effe56c11..7de46d4d9ebdb 100644 --- a/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java +++ b/shell/platform/android/io/flutter/embedding/android/AndroidKeyProcessor.java @@ -4,12 +4,12 @@ package io.flutter.embedding.android; -import android.util.Log; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import io.flutter.Log; import io.flutter.embedding.engine.systemchannels.KeyEventChannel; import io.flutter.plugin.editing.TextInputPlugin; import java.util.AbstractMap.SimpleImmutableEntry; diff --git a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java index 2b7c0879bcb76..e2d97c40ee174 100644 --- a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java +++ b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java @@ -10,12 +10,12 @@ import android.os.Handler; import android.os.Looper; import android.os.SystemClock; -import android.util.Log; import android.view.WindowManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import io.flutter.BuildConfig; import io.flutter.FlutterInjector; +import io.flutter.Log; import io.flutter.embedding.engine.FlutterJNI; import io.flutter.util.PathUtils; import io.flutter.view.VsyncWaiter; diff --git a/shell/platform/android/io/flutter/embedding/engine/loader/ResourceExtractor.java b/shell/platform/android/io/flutter/embedding/engine/loader/ResourceExtractor.java index f8714dc813fcd..a0b7382edf3da 100644 --- a/shell/platform/android/io/flutter/embedding/engine/loader/ResourceExtractor.java +++ b/shell/platform/android/io/flutter/embedding/engine/loader/ResourceExtractor.java @@ -11,10 +11,10 @@ import android.content.res.AssetManager; import android.os.AsyncTask; import android.os.Build; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; import io.flutter.BuildConfig; +import io.flutter.Log; import java.io.*; import java.util.ArrayList; import java.util.Collection; diff --git a/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java b/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java index 03fc178498d8e..d94b90c47b86b 100644 --- a/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java +++ b/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java @@ -4,11 +4,11 @@ package io.flutter.plugin.common; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import io.flutter.BuildConfig; +import io.flutter.Log; import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler; import io.flutter.plugin.common.BinaryMessenger.BinaryReply; import java.nio.ByteBuffer; diff --git a/shell/platform/android/io/flutter/plugin/common/ErrorLogResult.java b/shell/platform/android/io/flutter/plugin/common/ErrorLogResult.java index d4acc77ea0f7c..90b1c541df39c 100644 --- a/shell/platform/android/io/flutter/plugin/common/ErrorLogResult.java +++ b/shell/platform/android/io/flutter/plugin/common/ErrorLogResult.java @@ -4,9 +4,9 @@ package io.flutter.plugin.common; -import android.util.Log; import androidx.annotation.Nullable; import io.flutter.BuildConfig; +import io.flutter.Log; /** * An implementation of {@link MethodChannel.Result} that writes error results to the Android log. diff --git a/shell/platform/android/io/flutter/plugin/common/EventChannel.java b/shell/platform/android/io/flutter/plugin/common/EventChannel.java index f7d2e3e84c2f2..fed8b053e93ed 100644 --- a/shell/platform/android/io/flutter/plugin/common/EventChannel.java +++ b/shell/platform/android/io/flutter/plugin/common/EventChannel.java @@ -4,9 +4,9 @@ package io.flutter.plugin.common; -import android.util.Log; import androidx.annotation.UiThread; import io.flutter.BuildConfig; +import io.flutter.Log; import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler; import io.flutter.plugin.common.BinaryMessenger.BinaryReply; import java.nio.ByteBuffer; diff --git a/shell/platform/android/io/flutter/plugin/common/FlutterException.java b/shell/platform/android/io/flutter/plugin/common/FlutterException.java index 8748efdc223b5..ffcce9eb046b5 100644 --- a/shell/platform/android/io/flutter/plugin/common/FlutterException.java +++ b/shell/platform/android/io/flutter/plugin/common/FlutterException.java @@ -4,8 +4,8 @@ package io.flutter.plugin.common; -import android.util.Log; import io.flutter.BuildConfig; +import io.flutter.Log; /** Thrown to indicate that a Flutter method invocation failed on the Flutter side. */ public class FlutterException extends RuntimeException { diff --git a/shell/platform/android/io/flutter/plugin/common/MethodChannel.java b/shell/platform/android/io/flutter/plugin/common/MethodChannel.java index 81e50e3b938c3..8b1336a7e63c9 100644 --- a/shell/platform/android/io/flutter/plugin/common/MethodChannel.java +++ b/shell/platform/android/io/flutter/plugin/common/MethodChannel.java @@ -4,11 +4,11 @@ package io.flutter.plugin.common; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import io.flutter.BuildConfig; +import io.flutter.Log; import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler; import io.flutter.plugin.common.BinaryMessenger.BinaryReply; import java.io.PrintWriter; diff --git a/shell/platform/android/io/flutter/plugin/common/StandardMessageCodec.java b/shell/platform/android/io/flutter/plugin/common/StandardMessageCodec.java index 9a99de87bf116..625f522cac0a2 100644 --- a/shell/platform/android/io/flutter/plugin/common/StandardMessageCodec.java +++ b/shell/platform/android/io/flutter/plugin/common/StandardMessageCodec.java @@ -4,8 +4,8 @@ package io.flutter.plugin.common; -import android.util.Log; import io.flutter.BuildConfig; +import io.flutter.Log; import java.io.ByteArrayOutputStream; import java.math.BigInteger; import java.nio.ByteBuffer; diff --git a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java index c7de3c2c0ec6c..05a6240e67092 100644 --- a/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java +++ b/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java @@ -11,7 +11,6 @@ import android.content.Context; import android.os.Build; import android.util.DisplayMetrics; -import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; @@ -20,6 +19,7 @@ import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; +import io.flutter.Log; import io.flutter.embedding.android.AndroidTouchProcessor; import io.flutter.embedding.android.FlutterImageView; import io.flutter.embedding.android.FlutterView; diff --git a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java index 993f88efb2a8c..b40ef87e5ccc7 100644 --- a/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java +++ b/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java @@ -17,7 +17,6 @@ import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.os.Bundle; -import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.View; @@ -29,6 +28,7 @@ import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import io.flutter.Log; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; diff --git a/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/shell/platform/android/io/flutter/view/AccessibilityBridge.java index d7bdf3926432e..cd50894516783 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -15,7 +15,6 @@ import android.os.Bundle; import android.os.Handler; import android.provider.Settings; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.WindowInsets; @@ -28,6 +27,7 @@ import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; import io.flutter.BuildConfig; +import io.flutter.Log; import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; import io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate; import io.flutter.util.Predicate; diff --git a/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java b/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java index 2823eb795d17b..33f18ef579c24 100644 --- a/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java +++ b/shell/platform/android/io/flutter/view/AccessibilityViewEmbedder.java @@ -9,7 +9,6 @@ import android.os.Build; import android.os.Bundle; import android.os.Parcel; -import android.util.Log; import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; @@ -20,6 +19,7 @@ import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import io.flutter.Log; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -502,9 +502,9 @@ private Long getSourceNodeId(@NonNull AccessibilityNodeInfo node) { try { return (Long) getSourceNodeId.invoke(node); } catch (IllegalAccessException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to access getSourceNodeId method.", e); } catch (InvocationTargetException e) { - Log.w(TAG, e); + Log.w(TAG, "The getSourceNodeId method threw an exception when invoked.", e); } return null; } @@ -523,9 +523,9 @@ private Long getChildId(@NonNull AccessibilityNodeInfo node, int child) { // type ReflectiveOperationException. As a workaround either create individual // catch statements, or catch Exception. [NewApi] } catch (IllegalAccessException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to access getChildId method.", e); } catch (InvocationTargetException e) { - Log.w(TAG, e); + Log.w(TAG, "The getChildId method threw an exception when invoked.", e); } } else { try { @@ -536,9 +536,9 @@ private Long getChildId(@NonNull AccessibilityNodeInfo node, int child) { // type ReflectiveOperationException. As a workaround either create individual // catch statements, or catch Exception. [NewApi] } catch (IllegalAccessException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to access longArrayGetIndex method or the childNodeId field.", e); } catch (InvocationTargetException | ArrayIndexOutOfBoundsException e) { - Log.w(TAG, e); + Log.w(TAG, "The longArrayGetIndex method threw an exception when invoked.", e); } } return null; @@ -555,9 +555,9 @@ private Long getParentNodeId(@NonNull AccessibilityNodeInfo node) { // type ReflectiveOperationException. As a workaround either create individual // catch statements, or catch Exception. [NewApi] } catch (IllegalAccessException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to access getParentNodeId method.", e); } catch (InvocationTargetException e) { - Log.w(TAG, e); + Log.w(TAG, "The getParentNodeId method threw an exception when invoked.", e); } } @@ -620,9 +620,9 @@ private Long getRecordSourceNodeId(@NonNull AccessibilityRecord node) { try { return (Long) getRecordSourceNodeId.invoke(node); } catch (IllegalAccessException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to access the getRecordSourceNodeId method.", e); } catch (InvocationTargetException e) { - Log.w(TAG, e); + Log.w(TAG, "The getRecordSourceNodeId method threw an exception when invoked.", e); } return null; } diff --git a/shell/platform/android/io/flutter/view/FlutterNativeView.java b/shell/platform/android/io/flutter/view/FlutterNativeView.java index ea01176ebcec6..2d5ee8c40ad56 100644 --- a/shell/platform/android/io/flutter/view/FlutterNativeView.java +++ b/shell/platform/android/io/flutter/view/FlutterNativeView.java @@ -6,9 +6,9 @@ import android.app.Activity; import android.content.Context; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.UiThread; +import io.flutter.Log; import io.flutter.app.FlutterPluginRegistry; import io.flutter.embedding.engine.FlutterEngine.EngineLifecycleListener; import io.flutter.embedding.engine.FlutterJNI; diff --git a/shell/platform/android/io/flutter/view/FlutterView.java b/shell/platform/android/io/flutter/view/FlutterView.java index 9899e1714b255..50598cd7344f4 100644 --- a/shell/platform/android/io/flutter/view/FlutterView.java +++ b/shell/platform/android/io/flutter/view/FlutterView.java @@ -19,7 +19,6 @@ import android.os.Handler; import android.text.format.DateFormat; import android.util.AttributeSet; -import android.util.Log; import android.util.SparseArray; import android.view.DisplayCutout; import android.view.KeyEvent; @@ -41,6 +40,7 @@ import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.annotation.UiThread; +import io.flutter.Log; import io.flutter.app.FlutterPluginRegistry; import io.flutter.embedding.android.AndroidKeyProcessor; import io.flutter.embedding.android.AndroidTouchProcessor; diff --git a/tools/android_illegal_imports.py b/tools/android_illegal_imports.py new file mode 100644 index 0000000000000..2a2d5ac1fbf1f --- /dev/null +++ b/tools/android_illegal_imports.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# 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. + +import argparse +import os +import subprocess +import sys + +ANDROID_LOG_CLASS = 'android.util.Log' +FLUTTER_LOG_CLASS = 'io.flutter.Log' + +def main(): + parser = argparse.ArgumentParser(description='Checks Flutter Android library for forbidden imports') + parser.add_argument('--stamp', type=str, required=True) + parser.add_argument('--files', type=str, required=True, nargs='+') + args = parser.parse_args() + + open(args.stamp, 'wa').close() + + bad_files = [] + + for file in args.files: + if file.endswith(os.path.join('io', 'flutter', 'Log.java')): + continue + with open(file) as f: + if ANDROID_LOG_CLASS in f.read(): + bad_files.append(file) + + if bad_files: + print('') + print('Illegal import %s detected in the following files:' % ANDROID_LOG_CLASS) + for bad_file in bad_files: + print(' - ' + bad_file) + print('Use %s instead.' % FLUTTER_LOG_CLASS) + print('') + return 1 + + return 0 + + +if __name__ == '__main__': + sys.exit(main())