diff --git a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java index 4f23d52951a..01bee5b36b4 100644 --- a/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java +++ b/appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java @@ -16,6 +16,7 @@ import static com.google.android.gms.common.internal.Preconditions.checkNotNull; +import android.annotation.SuppressLint; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -45,6 +46,8 @@ public class DebugAppCheckProvider implements AppCheckProvider { private final RetryManager retryManager; private final Task debugSecretTask; + // TODO(b/258273630): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public DebugAppCheckProvider(@NonNull FirebaseApp firebaseApp, @Nullable String debugSecret) { checkNotNull(firebaseApp); this.networkClient = new NetworkClient(firebaseApp); diff --git a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java index 13381af83a6..8a5e2622a9b 100644 --- a/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java +++ b/appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java @@ -14,6 +14,7 @@ package com.google.firebase.appcheck.playintegrity.internal; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.google.android.gms.tasks.Task; @@ -41,6 +42,8 @@ public class PlayIntegrityAppCheckProvider implements AppCheckProvider { private final ExecutorService backgroundExecutor; private final RetryManager retryManager; + // TODO(b/258273630): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public PlayIntegrityAppCheckProvider(@NonNull FirebaseApp firebaseApp) { this( firebaseApp.getOptions().getGcmSenderId(), diff --git a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java index f44867c39ee..e88ee9c0e9b 100644 --- a/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java +++ b/appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java @@ -17,6 +17,7 @@ import static com.google.android.gms.common.internal.Preconditions.checkNotEmpty; import static com.google.android.gms.common.internal.Preconditions.checkNotNull; +import android.annotation.SuppressLint; import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; @@ -56,6 +57,8 @@ public class SafetyNetAppCheckProvider implements AppCheckProvider { private final String apiKey; /** @param firebaseApp the FirebaseApp to which this Factory is tied. */ + // TODO(b/258273630): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public SafetyNetAppCheckProvider(@NonNull FirebaseApp firebaseApp) { this( firebaseApp, diff --git a/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java b/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java index 769bd1048d3..3ed17999814 100644 --- a/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java +++ b/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java @@ -16,6 +16,7 @@ import static com.google.android.gms.common.internal.Preconditions.checkNotNull; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -57,6 +58,8 @@ public class DefaultFirebaseAppCheck extends FirebaseAppCheck { private AppCheckProvider appCheckProvider; private AppCheckToken cachedToken; + // TODO(b/258273630): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public DefaultFirebaseAppCheck( @NonNull FirebaseApp firebaseApp, @NonNull Provider heartBeatController) { diff --git a/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultTokenRefresher.java b/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultTokenRefresher.java index 8e7f6722046..8cec32c540a 100644 --- a/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultTokenRefresher.java +++ b/appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultTokenRefresher.java @@ -18,6 +18,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.google.android.gms.tasks.OnFailureListener; @@ -41,6 +42,8 @@ public class DefaultTokenRefresher { private volatile ScheduledFuture refreshFuture; private volatile long delayAfterFailureSeconds; + // TODO(b/258273630): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") DefaultTokenRefresher(@NonNull DefaultFirebaseAppCheck firebaseAppCheck) { this(checkNotNull(firebaseAppCheck), Executors.newScheduledThreadPool(/* corePoolSize= */ 1)); } diff --git a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java index cc4122d7d0d..4d1ba164ca3 100644 --- a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java +++ b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java @@ -19,6 +19,7 @@ import static com.google.firebase.appdistribution.impl.TaskUtils.runAsyncInTask; import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskException; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -52,6 +53,8 @@ class AabUpdater { @GuardedBy("updateAabLock") private boolean hasBeenSentToPlayForCurrentTask = false; + // TODO(b/258264924): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") AabUpdater() { this( FirebaseAppDistributionLifecycleNotifier.getInstance(), diff --git a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java index 3945b4234e5..a54abd1a268 100644 --- a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java +++ b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java @@ -19,6 +19,7 @@ import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskException; import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskResult; +import android.annotation.SuppressLint; import android.content.Context; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; @@ -62,6 +63,8 @@ class ApkUpdater { private final Object updateTaskLock = new Object(); + // TODO(b/258264924): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ApkUpdater(@NonNull FirebaseApp firebaseApp, @NonNull ApkInstaller apkInstaller) { this( Executors.newSingleThreadExecutor(), diff --git a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionTesterApiClient.java b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionTesterApiClient.java index f5dfd8e4173..8d81833a1e4 100644 --- a/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionTesterApiClient.java +++ b/firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionTesterApiClient.java @@ -16,6 +16,7 @@ import static com.google.firebase.appdistribution.impl.TaskUtils.runAsyncInTask; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; @@ -63,6 +64,9 @@ private interface FidDependentJob { private final FirebaseApp firebaseApp; private final Provider firebaseInstallationsApiProvider; private final TesterApiHttpClient testerApiHttpClient; + + // TODO(b/258264924): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private final Executor taskExecutor = Executors.newSingleThreadExecutor(); FirebaseAppDistributionTesterApiClient( diff --git a/firebase-common/src/main/java/com/google/firebase/concurrent/SequentialExecutor.java b/firebase-common/src/main/java/com/google/firebase/concurrent/SequentialExecutor.java index cd190a914c6..db5f4f3a374 100644 --- a/firebase-common/src/main/java/com/google/firebase/concurrent/SequentialExecutor.java +++ b/firebase-common/src/main/java/com/google/firebase/concurrent/SequentialExecutor.java @@ -1,3 +1,17 @@ +// Copyright 2022 Google LLC +// +// 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.google.firebase.concurrent; import static com.google.android.gms.common.internal.Preconditions.checkNotNull; diff --git a/firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigComponent.java b/firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigComponent.java index 83b867a65f2..543b95cfec0 100644 --- a/firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigComponent.java +++ b/firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigComponent.java @@ -14,6 +14,7 @@ package com.google.firebase.remoteconfig; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import androidx.annotation.GuardedBy; @@ -87,6 +88,8 @@ public class RemoteConfigComponent { private Map customHeaders = new HashMap<>(); /** Firebase Remote Config Component constructor. */ + // TODO(b/258275481): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") RemoteConfigComponent( Context context, FirebaseApp firebaseApp, @@ -211,6 +214,8 @@ public synchronized void setCustomHeaders(Map customHeaders) { this.customHeaders = customHeaders; } + // TODO(b/258275481): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private ConfigCacheClient getCacheClient(String namespace, String configStoreType) { String fileName = String.format( diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java index 4c4ecad1795..fd62712ef22 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.firebase.crashlytics.internal.common; +import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.ApplicationExitInfo; import android.content.Context; @@ -734,6 +735,9 @@ private Task logAnalyticsAppExceptionEvent(long timestamp) { return Tasks.forResult(null); } Logger.getLogger().d("Logging app exception event to Firebase Analytics"); + + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") final ThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); return Tasks.call( executor, diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/ExecutorUtils.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/ExecutorUtils.java index 9147921af73..77fafe9adc5 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/ExecutorUtils.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/ExecutorUtils.java @@ -16,6 +16,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; +import android.annotation.SuppressLint; import com.google.firebase.crashlytics.internal.Logger; import java.util.Locale; import java.util.concurrent.ExecutorService; @@ -43,6 +44,8 @@ public static ExecutorService buildSingleThreadExecutorService(String name) { public static ScheduledExecutorService buildSingleThreadScheduledExecutorService(String name) { final ThreadFactory threadFactory = ExecutorUtils.getNamedThreadFactory(name); + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(threadFactory); ExecutorUtils.addDelayedShutdownHook(name, executor); @@ -70,6 +73,8 @@ public void onRun() { }; } + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static ExecutorService newSingleThreadExecutor( ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) { return Executors.unconfigurableExecutorService( @@ -88,11 +93,14 @@ private static void addDelayedShutdownHook(String serviceName, ExecutorService s serviceName, service, DEFAULT_TERMINATION_TIMEOUT, SECONDS); } + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static void addDelayedShutdownHook( final String serviceName, final ExecutorService service, final long terminationTimeout, final TimeUnit timeUnit) { + Runtime.getRuntime() .addShutdownHook( new Thread( diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java index d25c86c0eff..39c79d07c3c 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java @@ -62,6 +62,8 @@ final class ReportQueue { onDemandCounter); } + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") ReportQueue( double ratePerMinute, double base, @@ -120,7 +122,8 @@ TaskCompletionSource enqueueReport( } } - @SuppressLint("DiscouragedApi") // best effort only + // TODO(b/258263226): Migrate to go/firebase-android-executors + @SuppressLint({"DiscouragedApi", "ThreadPoolCreation"}) // best effort only public void flushScheduledReportsIfAble() { CountDownLatch latch = new CountDownLatch(1); new Thread( diff --git a/firebase-database/src/main/java/com/google/firebase/database/core/ThreadPoolEventTarget.java b/firebase-database/src/main/java/com/google/firebase/database/core/ThreadPoolEventTarget.java index 90bd199e496..f7c8b4e5df7 100644 --- a/firebase-database/src/main/java/com/google/firebase/database/core/ThreadPoolEventTarget.java +++ b/firebase-database/src/main/java/com/google/firebase/database/core/ThreadPoolEventTarget.java @@ -14,6 +14,7 @@ package com.google.firebase.database.core; +import android.annotation.SuppressLint; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; @@ -25,6 +26,8 @@ class ThreadPoolEventTarget implements EventTarget { private final ThreadPoolExecutor executor; + // TODO(b/258277572): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ThreadPoolEventTarget( final ThreadFactory wrappedFactory, final ThreadInitializer threadInitializer) { int poolSize = 1; diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/Transaction.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/Transaction.java index d235fc8e7b0..42c62125dd1 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/core/Transaction.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/core/Transaction.java @@ -17,6 +17,7 @@ import static com.google.firebase.firestore.util.Assert.fail; import static com.google.firebase.firestore.util.Assert.hardAssert; +import android.annotation.SuppressLint; import androidx.annotation.Nullable; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; @@ -162,6 +163,9 @@ private static Executor createDefaultExecutor() { int maxPoolSize = corePoolSize; int keepAliveSeconds = 1; LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + + // TODO(b/258277574): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") ThreadPoolExecutor executor = new ThreadPoolExecutor( corePoolSize, maxPoolSize, keepAliveSeconds, TimeUnit.SECONDS, queue); diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/util/AsyncQueue.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/util/AsyncQueue.java index c368022f07a..532ea0dc342 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/util/AsyncQueue.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/util/AsyncQueue.java @@ -17,6 +17,7 @@ import static com.google.firebase.firestore.util.Assert.fail; import static com.google.firebase.firestore.util.Assert.hardAssert; +import android.annotation.SuppressLint; import android.os.Handler; import android.os.Looper; import androidx.annotation.NonNull; @@ -243,6 +244,8 @@ public Thread newThread(@NonNull Runnable runnable) { } } + // TODO(b/258277574): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") SynchronizedShutdownAwareExecutor() { DelayedStartFactory threadFactory = new DelayedStartFactory(); diff --git a/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/AbtIntegrationHelper.java b/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/AbtIntegrationHelper.java index 8ea864b51f3..1927a4cd1de 100644 --- a/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/AbtIntegrationHelper.java +++ b/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/AbtIntegrationHelper.java @@ -14,6 +14,7 @@ package com.google.firebase.inappmessaging.internal; +import android.annotation.SuppressLint; import androidx.annotation.VisibleForTesting; import com.google.firebase.abt.AbtException; import com.google.firebase.abt.AbtExperimentInfo; @@ -33,7 +34,10 @@ public class AbtIntegrationHelper { private final FirebaseABTesting abTesting; - @VisibleForTesting Executor executor = Executors.newSingleThreadExecutor(); + // TODO(b/258280977): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") + @VisibleForTesting + Executor executor = Executors.newSingleThreadExecutor(); @Inject public AbtIntegrationHelper(FirebaseABTesting abTesting) { diff --git a/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/DeveloperListenerManager.java b/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/DeveloperListenerManager.java index ff1d3383849..bc6dc381445 100644 --- a/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/DeveloperListenerManager.java +++ b/firebase-inappmessaging/src/main/java/com/google/firebase/inappmessaging/internal/DeveloperListenerManager.java @@ -14,6 +14,7 @@ package com.google.firebase.inappmessaging.internal; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import com.google.firebase.inappmessaging.FirebaseInAppMessagingClickListener; import com.google.firebase.inappmessaging.FirebaseInAppMessagingDismissListener; @@ -56,6 +57,9 @@ public class DeveloperListenerManager { registeredImpressionListeners = new HashMap<>(); private static BlockingQueue mCallbackQueue = new LinkedBlockingQueue<>(); + + // TODO(b/258280977): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static final ThreadPoolExecutor CALLBACK_QUEUE_EXECUTOR = new ThreadPoolExecutor( POOL_SIZE, @@ -182,6 +186,8 @@ static class FIAMThreadFactory implements ThreadFactory { @SuppressWarnings("ThreadPriorityCheck") @Override + // TODO(b/258280977): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public Thread newThread(@NonNull Runnable r) { Thread t = new Thread(r, "FIAM-" + mNameSuffix + threadNumber.getAndIncrement()); t.setDaemon(false); diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java index 5f1b1e7f90d..62385d5caca 100644 --- a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java +++ b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java @@ -14,6 +14,7 @@ package com.google.firebase.installations; +import android.annotation.SuppressLint; import android.text.TextUtils; import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; @@ -96,6 +97,8 @@ public class FirebaseInstallations implements FirebaseInstallationsApi { private final AtomicInteger mCount = new AtomicInteger(1); @Override + // TODO(b/258422917): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public Thread newThread(Runnable r) { return new Thread( r, String.format("firebase-installations-executor-%d", mCount.getAndIncrement())); @@ -123,6 +126,8 @@ public Thread newThread(Runnable r) { + "Please retry your last request."; /** package private constructor. */ + // TODO(b/258422917): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") FirebaseInstallations( FirebaseApp firebaseApp, @NonNull Provider heartBeatProvider) { this( @@ -142,6 +147,8 @@ public Thread newThread(Runnable r) { new RandomFidGenerator()); } + // TODO(b/258422917): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") FirebaseInstallations( ExecutorService backgroundExecutor, FirebaseApp firebaseApp, diff --git a/firebase-messaging-directboot/firebase-messaging-directboot.gradle b/firebase-messaging-directboot/firebase-messaging-directboot.gradle index adca39b77ad..aae84d0dc49 100644 --- a/firebase-messaging-directboot/firebase-messaging-directboot.gradle +++ b/firebase-messaging-directboot/firebase-messaging-directboot.gradle @@ -27,10 +27,6 @@ android { timeOutInMs 60 * 1000 } - lintOptions { - abortOnError false - } - compileSdkVersion project.targetSdkVersion defaultConfig { minSdkVersion 19 diff --git a/firebase-messaging-directboot/src/main/java/com/google/firebase/messaging/directboot/threads/PoolableExecutors.java b/firebase-messaging-directboot/src/main/java/com/google/firebase/messaging/directboot/threads/PoolableExecutors.java index 529fe04dcd5..431b127976a 100644 --- a/firebase-messaging-directboot/src/main/java/com/google/firebase/messaging/directboot/threads/PoolableExecutors.java +++ b/firebase-messaging-directboot/src/main/java/com/google/firebase/messaging/directboot/threads/PoolableExecutors.java @@ -14,6 +14,7 @@ package com.google.firebase.messaging.directboot.threads; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import com.google.errorprone.annotations.CompileTimeConstant; import java.util.concurrent.ExecutorService; @@ -52,6 +53,8 @@ private static class DefaultExecutorFactory implements ExecutorFactory { /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool(ThreadPriority priority) { // NOTE: Cached threadpools automatically time out all threads. They have no concept of core // threads; the queue blocks until a thread is started. @@ -61,6 +64,8 @@ public ExecutorService newThreadPool(ThreadPriority priority) { /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool(ThreadFactory threadFactory, ThreadPriority priority) { return Executors.unconfigurableExecutorService(Executors.newCachedThreadPool(threadFactory)); } @@ -79,6 +84,8 @@ public ExecutorService newThreadPool(int maxConcurrency, ThreadPriority priority /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool( int maxConcurrency, ThreadFactory threadFactory, ThreadPriority priority) { ThreadPoolExecutor executor = @@ -115,6 +122,8 @@ public ExecutorService newSingleThreadExecutor( /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ScheduledExecutorService newScheduledThreadPool( int maxConcurrency, ThreadPriority priority) { // NOTE: There's no way to make a scheduled executor stop threads automatically, because @@ -128,6 +137,8 @@ public ScheduledExecutorService newScheduledThreadPool( /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ScheduledExecutorService newScheduledThreadPool( int maxConcurrency, ThreadFactory threadFactory, ThreadPriority priority) { return Executors.unconfigurableScheduledExecutorService( @@ -136,6 +147,8 @@ public ScheduledExecutorService newScheduledThreadPool( @Override @NonNull + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public void executeOneOff( @CompileTimeConstant final String moduleName, @CompileTimeConstant final String name, @@ -146,6 +159,8 @@ public void executeOneOff( @Override @NonNull + // TODO(b/258424598): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public Future submitOneOff( @CompileTimeConstant final String moduleName, @CompileTimeConstant final String name, diff --git a/firebase-messaging/firebase-messaging.gradle b/firebase-messaging/firebase-messaging.gradle index a220aae3c1f..93a4a9994c5 100644 --- a/firebase-messaging/firebase-messaging.gradle +++ b/firebase-messaging/firebase-messaging.gradle @@ -57,11 +57,6 @@ android { timeOutInMs 60 * 1000 } - - lintOptions { - abortOnError false - } - compileSdkVersion project.targetSdkVersion defaultConfig { minSdkVersion 19 diff --git a/firebase-messaging/src/main/java/com/google/firebase/messaging/FcmExecutors.java b/firebase-messaging/src/main/java/com/google/firebase/messaging/FcmExecutors.java index 90bfae54107..385af046e99 100644 --- a/firebase-messaging/src/main/java/com/google/firebase/messaging/FcmExecutors.java +++ b/firebase-messaging/src/main/java/com/google/firebase/messaging/FcmExecutors.java @@ -15,6 +15,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; +import android.annotation.SuppressLint; import com.google.android.gms.common.util.concurrent.NamedThreadFactory; import com.google.firebase.messaging.threads.PoolableExecutors; import com.google.firebase.messaging.threads.ThreadPriority; @@ -54,6 +55,8 @@ static Executor newFileIOExecutor() { } @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static Executor newCachedSingleThreadExecutor(String threadName) { // Creates a single threaded executor that only keeps the thread alive for a short time when // idle to reduce resource use. @@ -68,23 +71,31 @@ private static Executor newCachedSingleThreadExecutor(String threadName) { /** Creates a single threaded ScheduledPoolExecutor. */ @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static ScheduledExecutorService newTopicsSyncExecutor() { return new ScheduledThreadPoolExecutor( /* corePoolSize= */ 1, new NamedThreadFactory(THREAD_TOPICS_IO)); } @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static ExecutorService newNetworkIOExecutor() { // TODO(b/148493968): consider use PoolableExecutors for all FCM threading return Executors.newSingleThreadExecutor(new NamedThreadFactory(THREAD_NETWORK_IO)); } @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static ExecutorService newTaskExecutor() { return Executors.newSingleThreadExecutor(new NamedThreadFactory(THREAD_TASK)); } @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static ExecutorService newFileExecutor() { return Executors.newSingleThreadExecutor(new NamedThreadFactory(THREAD_FILE)); } @@ -97,6 +108,8 @@ static ExecutorService newIntentHandleExecutor() { /** Creates a single threaded ScheduledPoolExecutor. */ @SuppressWarnings("ThreadChecker") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static ScheduledExecutorService newInitExecutor() { return new ScheduledThreadPoolExecutor( /* corePoolSize= */ 1, new NamedThreadFactory(THREAD_INIT)); diff --git a/firebase-messaging/src/main/java/com/google/firebase/messaging/FirebaseMessaging.java b/firebase-messaging/src/main/java/com/google/firebase/messaging/FirebaseMessaging.java index ac9dedb21ce..c3fd8e2419c 100644 --- a/firebase-messaging/src/main/java/com/google/firebase/messaging/FirebaseMessaging.java +++ b/firebase-messaging/src/main/java/com/google/firebase/messaging/FirebaseMessaging.java @@ -367,6 +367,7 @@ public boolean isNotificationDelegationEnabled() { * @param enable Whether to enable or disable notification delegation. * @return A Task that completes when the notification delegation has been set. */ + @NonNull public Task setNotificationDelegationEnabled(boolean enable) { return ProxyNotificationInitializer.setEnableProxyNotification(initExecutor, context, enable); } @@ -548,6 +549,8 @@ synchronized void syncWithDelaySecondsInternal(long delaySeconds) { } @SuppressWarnings("FutureReturnValueIgnored") + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") void enqueueTaskWithDelaySeconds(Runnable task, long delaySeconds) { synchronized (FirebaseMessaging.class) { if (syncExecutor == null) { diff --git a/firebase-messaging/src/main/java/com/google/firebase/messaging/SyncTask.java b/firebase-messaging/src/main/java/com/google/firebase/messaging/SyncTask.java index 55d842a00a5..77230e96ab8 100644 --- a/firebase-messaging/src/main/java/com/google/firebase/messaging/SyncTask.java +++ b/firebase-messaging/src/main/java/com/google/firebase/messaging/SyncTask.java @@ -44,6 +44,8 @@ class SyncTask implements Runnable { private final FirebaseMessaging firebaseMessaging; @VisibleForTesting + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") ExecutorService processorExecutor = new ThreadPoolExecutor( /* corePoolSize= */ 0, diff --git a/firebase-messaging/src/main/java/com/google/firebase/messaging/WithinAppServiceConnection.java b/firebase-messaging/src/main/java/com/google/firebase/messaging/WithinAppServiceConnection.java index 3f2b7905431..ca0740b000f 100644 --- a/firebase-messaging/src/main/java/com/google/firebase/messaging/WithinAppServiceConnection.java +++ b/firebase-messaging/src/main/java/com/google/firebase/messaging/WithinAppServiceConnection.java @@ -16,6 +16,7 @@ import static com.google.firebase.messaging.FirebaseMessaging.TAG; import static com.google.firebase.messaging.WakeLockHolder.WAKE_LOCK_ACQUIRE_TIMEOUT_MILLIS; +import android.annotation.SuppressLint; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -104,6 +105,8 @@ void finish() { @GuardedBy("this") private boolean connectionInProgress = false; + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") WithinAppServiceConnection(Context context, String action) { // Class instances are owned by a static variable in FirebaseInstanceIdReceiver // and GcmReceiver so that they survive getting gc'd and reinstantiated, so use a diff --git a/firebase-messaging/src/main/java/com/google/firebase/messaging/threads/PoolableExecutors.java b/firebase-messaging/src/main/java/com/google/firebase/messaging/threads/PoolableExecutors.java index 18e50fa0373..dabdecbf795 100644 --- a/firebase-messaging/src/main/java/com/google/firebase/messaging/threads/PoolableExecutors.java +++ b/firebase-messaging/src/main/java/com/google/firebase/messaging/threads/PoolableExecutors.java @@ -14,6 +14,7 @@ package com.google.firebase.messaging.threads; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import com.google.errorprone.annotations.CompileTimeConstant; import java.util.concurrent.ExecutorService; @@ -52,6 +53,8 @@ private static class DefaultExecutorFactory implements ExecutorFactory { /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool(ThreadPriority priority) { // NOTE: Cached threadpools automatically time out all threads. They have no concept of core // threads; the queue blocks until a thread is started. @@ -61,6 +64,8 @@ public ExecutorService newThreadPool(ThreadPriority priority) { /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool(ThreadFactory threadFactory, ThreadPriority priority) { return Executors.unconfigurableExecutorService(Executors.newCachedThreadPool(threadFactory)); } @@ -79,6 +84,8 @@ public ExecutorService newThreadPool(int maxConcurrency, ThreadPriority priority /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ExecutorService newThreadPool( int maxConcurrency, ThreadFactory threadFactory, ThreadPriority priority) { ThreadPoolExecutor executor = @@ -115,6 +122,8 @@ public ExecutorService newSingleThreadExecutor( /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ScheduledExecutorService newScheduledThreadPool( int maxConcurrency, ThreadPriority priority) { // NOTE: There's no way to make a scheduled executor stop threads automatically, because @@ -128,6 +137,8 @@ public ScheduledExecutorService newScheduledThreadPool( /** {@inheritDoc} */ @NonNull @Override + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public ScheduledExecutorService newScheduledThreadPool( int maxConcurrency, ThreadFactory threadFactory, ThreadPriority priority) { return Executors.unconfigurableScheduledExecutorService( @@ -136,6 +147,8 @@ public ScheduledExecutorService newScheduledThreadPool( @Override @NonNull + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public void executeOneOff( @CompileTimeConstant final String moduleName, @CompileTimeConstant final String name, @@ -146,6 +159,8 @@ public void executeOneOff( @Override @NonNull + // TODO(b/258424124): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public Future submitOneOff( @CompileTimeConstant final String moduleName, @CompileTimeConstant final String name, diff --git a/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java b/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java index cbf8fb1f894..ac67275d045 100644 --- a/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java +++ b/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.firebase.ml.modeldownloader; +import android.annotation.SuppressLint; import android.os.Build.VERSION_CODES; import android.util.Log; import androidx.annotation.NonNull; @@ -51,6 +52,8 @@ public class FirebaseModelDownloader { private final FirebaseMlLogger eventLogger; @RequiresApi(api = VERSION_CODES.KITKAT) + // TODO(b/258424267): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") FirebaseModelDownloader( FirebaseApp firebaseApp, FirebaseInstallationsApi firebaseInstallationsApi) { this.firebaseOptions = firebaseApp.getOptions(); diff --git a/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/CustomModelDownloadService.java b/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/CustomModelDownloadService.java index 1775ba00d79..b046a6a3778 100644 --- a/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/CustomModelDownloadService.java +++ b/firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/internal/CustomModelDownloadService.java @@ -14,6 +14,7 @@ package com.google.firebase.ml.modeldownloader.internal; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageManager; import android.text.TextUtils; @@ -93,6 +94,8 @@ public class CustomModelDownloadService { private final Context context; private String downloadHost = FIREBASE_DOWNLOAD_HOST; + // TODO(b/258424267): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public CustomModelDownloadService( FirebaseApp firebaseApp, FirebaseInstallationsApi installationsApi) { context = firebaseApp.getApplicationContext(); diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/config/DeviceCacheManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/config/DeviceCacheManager.java index 012edfc8b81..e62f7e248f4 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/config/DeviceCacheManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/config/DeviceCacheManager.java @@ -14,6 +14,7 @@ package com.google.firebase.perf.config; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import androidx.annotation.Nullable; @@ -49,6 +50,8 @@ public DeviceCacheManager(ExecutorService serialExecutor) { this.serialExecutor = serialExecutor; } + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public static synchronized DeviceCacheManager getInstance() { if (instance == null) { instance = new DeviceCacheManager(Executors.newSingleThreadExecutor()); diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java index 7c27b59c3d9..06c505ddd51 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java @@ -16,6 +16,7 @@ import static com.google.firebase.perf.config.ConfigurationConstants.ExperimentTTID; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; @@ -66,6 +67,8 @@ public class RemoteConfigManager { @Nullable private Provider firebaseRemoteConfigProvider; @Nullable private FirebaseRemoteConfig firebaseRemoteConfig; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private RemoteConfigManager() { this( DeviceCacheManager.getInstance(), diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java b/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java index 2e1bb5cd8d3..16c0a93b358 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java @@ -14,6 +14,7 @@ package com.google.firebase.perf.metrics; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.Application; import android.app.Application.ActivityLifecycleCallbacks; @@ -133,6 +134,8 @@ public static AppStartTrace getInstance() { return instance != null ? instance : getInstance(TransportManager.getInstance(), new Clock()); } + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") static AppStartTrace getInstance(TransportManager transportManager, Clock clock) { if (instance == null) { synchronized (AppStartTrace.class) { diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/session/SessionManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/session/SessionManager.java index b482268adb3..ad9b1c04d00 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/session/SessionManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/session/SessionManager.java @@ -79,6 +79,8 @@ public void setApplicationContext(final Context appContext) { // Get PerfSession in main thread first, because it is possible that app changes fg/bg state // which creates a new perfSession, before the following is executed in background thread final PerfSession appStartSession = perfSession; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") ExecutorService executorService = Executors.newSingleThreadExecutor(); syncInitFuture = executorService.submit( diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/CpuGaugeCollector.java b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/CpuGaugeCollector.java index c34fd31dc72..e33d363c0aa 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/CpuGaugeCollector.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/CpuGaugeCollector.java @@ -16,6 +16,7 @@ import static android.system.Os.sysconf; +import android.annotation.SuppressLint; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.system.OsConstants; @@ -80,6 +81,8 @@ public class CpuGaugeCollector { @Nullable private ScheduledFuture cpuMetricCollectorJob = null; private long cpuMetricCollectionRateMs = UNSET_CPU_METRIC_COLLECTION_RATE; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") CpuGaugeCollector() { cpuMetricReadings = new ConcurrentLinkedQueue<>(); cpuMetricCollectorExecutor = Executors.newSingleThreadScheduledExecutor(); diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/GaugeManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/GaugeManager.java index 64cd5998a3a..0d15d3519c1 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/GaugeManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/GaugeManager.java @@ -14,6 +14,7 @@ package com.google.firebase.perf.session.gauges; +import android.annotation.SuppressLint; import android.content.Context; import androidx.annotation.Keep; import androidx.annotation.Nullable; @@ -63,9 +64,11 @@ public class GaugeManager { private ApplicationProcessState applicationProcessState = ApplicationProcessState.APPLICATION_PROCESS_STATE_UNKNOWN; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private GaugeManager() { this( - new Lazy<>(() -> Executors.newSingleThreadScheduledExecutor()), + new Lazy<>(Executors::newSingleThreadScheduledExecutor), TransportManager.getInstance(), ConfigResolver.getInstance(), null, diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/MemoryGaugeCollector.java b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/MemoryGaugeCollector.java index 8c3a3706a19..b221ba07760 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/MemoryGaugeCollector.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/session/gauges/MemoryGaugeCollector.java @@ -14,6 +14,7 @@ package com.google.firebase.perf.session.gauges; +import android.annotation.SuppressLint; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.firebase.perf.logging.AndroidLogger; @@ -52,6 +53,8 @@ public class MemoryGaugeCollector { @Nullable private ScheduledFuture memoryMetricCollectorJob = null; private long memoryMetricCollectionRateMs = UNSET_MEMORY_METRIC_COLLECTION_RATE; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") MemoryGaugeCollector() { this(Executors.newSingleThreadScheduledExecutor(), Runtime.getRuntime()); } diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/transport/TransportManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/transport/TransportManager.java index fab187ee6bf..dc99c77aa42 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/transport/TransportManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/transport/TransportManager.java @@ -17,6 +17,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MINUTES; +import android.annotation.SuppressLint; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; @@ -125,6 +126,8 @@ public class TransportManager implements AppStateCallback { private boolean isForegroundState = false; + // TODO(b/258263016): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private TransportManager() { // MAX_POOL_SIZE must always be 1. We only allow one thread in this Executor. The reason // we specifically use a ThreadPoolExecutor rather than generating one from ExecutorService diff --git a/firebase-segmentation/firebase-segmentation.gradle b/firebase-segmentation/firebase-segmentation.gradle index 215e75fa43e..c5081915348 100644 --- a/firebase-segmentation/firebase-segmentation.gradle +++ b/firebase-segmentation/firebase-segmentation.gradle @@ -38,6 +38,7 @@ android { } dependencies { + implementation project(':firebase-annotations') implementation project(':firebase-common') implementation project(':firebase-components') implementation project(':firebase-installations-interop') diff --git a/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentation.java b/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentation.java index b7e70bfef69..c9ba9550b38 100644 --- a/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentation.java +++ b/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentation.java @@ -30,7 +30,6 @@ import com.google.firebase.segmentation.remote.SegmentationServiceClient.Code; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; -import java.util.concurrent.Executors; /** Entry point of Firebase Segmentation SDK. */ public class FirebaseSegmentation { @@ -43,24 +42,29 @@ public class FirebaseSegmentation { private final SegmentationServiceClient backendServiceClient; private final Executor executor; - FirebaseSegmentation(FirebaseApp firebaseApp, FirebaseInstallationsApi firebaseInstallationsApi) { + FirebaseSegmentation( + FirebaseApp firebaseApp, + FirebaseInstallationsApi firebaseInstallationsApi, + Executor blockingExecutor) { this( firebaseApp, firebaseInstallationsApi, new CustomInstallationIdCache(firebaseApp), - new SegmentationServiceClient(firebaseApp.getApplicationContext())); + new SegmentationServiceClient(firebaseApp.getApplicationContext()), + blockingExecutor); } FirebaseSegmentation( FirebaseApp firebaseApp, FirebaseInstallationsApi firebaseInstallationsApi, CustomInstallationIdCache localCache, - SegmentationServiceClient backendServiceClient) { + SegmentationServiceClient backendServiceClient, + Executor blockingExecutor) { this.firebaseApp = firebaseApp; this.firebaseInstallationsApi = firebaseInstallationsApi; this.localCache = localCache; this.backendServiceClient = backendServiceClient; - this.executor = Executors.newFixedThreadPool(4); + this.executor = blockingExecutor; } /** diff --git a/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentationRegistrar.java b/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentationRegistrar.java index d005b206677..1620d043ae3 100644 --- a/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentationRegistrar.java +++ b/firebase-segmentation/src/main/java/com/google/firebase/segmentation/FirebaseSegmentationRegistrar.java @@ -16,13 +16,16 @@ import androidx.annotation.NonNull; import com.google.firebase.FirebaseApp; +import com.google.firebase.annotations.concurrent.Blocking; import com.google.firebase.components.Component; import com.google.firebase.components.ComponentRegistrar; import com.google.firebase.components.Dependency; +import com.google.firebase.components.Qualified; import com.google.firebase.installations.FirebaseInstallationsApi; import com.google.firebase.platforminfo.LibraryVersionComponent; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; /** @hide */ public class FirebaseSegmentationRegistrar implements ComponentRegistrar { @@ -31,15 +34,19 @@ public class FirebaseSegmentationRegistrar implements ComponentRegistrar { @Override @NonNull public List> getComponents() { + Qualified blockingExecutor = Qualified.qualified(Blocking.class, Executor.class); return Arrays.asList( Component.builder(FirebaseSegmentation.class) .name(LIBRARY_NAME) .add(Dependency.required(FirebaseApp.class)) .add(Dependency.required(FirebaseInstallationsApi.class)) + .add(Dependency.required(blockingExecutor)) .factory( c -> new FirebaseSegmentation( - c.get(FirebaseApp.class), c.get(FirebaseInstallationsApi.class))) + c.get(FirebaseApp.class), + c.get(FirebaseInstallationsApi.class), + c.get(blockingExecutor))) .build(), LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME)); } diff --git a/firebase-segmentation/src/test/java/com/google/firebase/segmentation/FirebaseSegmentationTest.java b/firebase-segmentation/src/test/java/com/google/firebase/segmentation/FirebaseSegmentationTest.java index 6a8a37485c2..1e6fb7b7106 100644 --- a/firebase-segmentation/src/test/java/com/google/firebase/segmentation/FirebaseSegmentationTest.java +++ b/firebase-segmentation/src/test/java/com/google/firebase/segmentation/FirebaseSegmentationTest.java @@ -134,7 +134,11 @@ public void cleanUp() throws Exception { public void testUpdateCustomInstallationId_CacheOk_BackendOk() throws Exception { FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, actualCache, backendClientReturnsOk); + firebaseApp, + firebaseInstallationsApi, + actualCache, + backendClientReturnsOk, + taskExecutor); // No exception, means success. TestOnCompleteListener onCompleteListener = new TestOnCompleteListener<>(); @@ -153,7 +157,11 @@ public void testUpdateCustomInstallationId_CacheOk_BackendError_Retryable() throws InterruptedException { FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, actualCache, backendClientReturnsError); + firebaseApp, + firebaseInstallationsApi, + actualCache, + backendClientReturnsError, + taskExecutor); // Expect exception try { @@ -185,7 +193,11 @@ public void testUpdateCustomInstallationId_CacheOk_BackendError_NotRetryable() .thenReturn(SegmentationServiceClient.Code.CONFLICT); FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, actualCache, backendClientReturnsError); + firebaseApp, + firebaseInstallationsApi, + actualCache, + backendClientReturnsError, + taskExecutor); // Expect exception try { @@ -210,7 +222,11 @@ public void testUpdateCustomInstallationId_CacheOk_BackendError_NotRetryable() public void testUpdateCustomInstallationId_CacheError_BackendOk() throws InterruptedException { FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, cacheReturnsError, backendClientReturnsOk); + firebaseApp, + firebaseInstallationsApi, + cacheReturnsError, + backendClientReturnsOk, + taskExecutor); // Expect exception try { @@ -237,7 +253,11 @@ public void testClearCustomInstallationId_CacheOk_BackendOk() throws Exception { CustomInstallationIdCache.CacheStatus.SYNCED)); FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, actualCache, backendClientReturnsOk); + firebaseApp, + firebaseInstallationsApi, + actualCache, + backendClientReturnsOk, + taskExecutor); // No exception, means success. TestOnCompleteListener onCompleteListener = new TestOnCompleteListener<>(); @@ -258,7 +278,11 @@ public void testClearCustomInstallationId_CacheOk_BackendError() throws Exceptio CustomInstallationIdCache.CacheStatus.SYNCED)); FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, actualCache, backendClientReturnsError); + firebaseApp, + firebaseInstallationsApi, + actualCache, + backendClientReturnsError, + taskExecutor); // Expect exception try { @@ -286,7 +310,11 @@ public void testClearCustomInstallationId_CacheOk_BackendError() throws Exceptio public void testClearCustomInstallationId_CacheError_BackendOk() throws InterruptedException { FirebaseSegmentation firebaseSegmentation = new FirebaseSegmentation( - firebaseApp, firebaseInstallationsApi, cacheReturnsError, backendClientReturnsOk); + firebaseApp, + firebaseInstallationsApi, + cacheReturnsError, + backendClientReturnsOk, + taskExecutor); // Expect exception try { diff --git a/firebase-storage/src/main/java/com/google/firebase/storage/StorageTaskScheduler.java b/firebase-storage/src/main/java/com/google/firebase/storage/StorageTaskScheduler.java index d428ef3692f..1245e9668ea 100644 --- a/firebase-storage/src/main/java/com/google/firebase/storage/StorageTaskScheduler.java +++ b/firebase-storage/src/main/java/com/google/firebase/storage/StorageTaskScheduler.java @@ -14,6 +14,7 @@ package com.google.firebase.storage; +import android.annotation.SuppressLint; import androidx.annotation.NonNull; import androidx.annotation.RestrictTo; import java.util.concurrent.BlockingQueue; @@ -36,21 +37,33 @@ public class StorageTaskScheduler { public static StorageTaskScheduler sInstance = new StorageTaskScheduler(); private static BlockingQueue mCommandQueue = new LinkedBlockingQueue<>(); + + // TODO(b/258426744): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static final ThreadPoolExecutor COMMAND_POOL_EXECUTOR = new ThreadPoolExecutor( 5, 5, 5, TimeUnit.SECONDS, mCommandQueue, new StorageThreadFactory("Command-")); private static BlockingQueue mUploadQueue = new LinkedBlockingQueue<>(); + + // TODO(b/258426744): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static final ThreadPoolExecutor UPLOAD_QUEUE_EXECUTOR = new ThreadPoolExecutor( 2, 2, 5, TimeUnit.SECONDS, mUploadQueue, new StorageThreadFactory("Upload-")); private static BlockingQueue mDownloadQueue = new LinkedBlockingQueue<>(); + + // TODO(b/258426744): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static final ThreadPoolExecutor DOWNLOAD_QUEUE_EXECUTOR = new ThreadPoolExecutor( 3, 3, 5, TimeUnit.SECONDS, mDownloadQueue, new StorageThreadFactory("Download-")); private static BlockingQueue mCallbackQueue = new LinkedBlockingQueue<>(); + + // TODO(b/258426744): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") private static final ThreadPoolExecutor CALLBACK_QUEUE_EXECUTOR = new ThreadPoolExecutor( 1, 1, 5, TimeUnit.SECONDS, mCallbackQueue, new StorageThreadFactory("Callbacks-")); @@ -101,6 +114,8 @@ static class StorageThreadFactory implements ThreadFactory { @Override @SuppressWarnings("ThreadPriorityCheck") + // TODO(b/258426744): Migrate to go/firebase-android-executors + @SuppressLint("ThreadPoolCreation") public Thread newThread(@NonNull Runnable r) { Thread t = new Thread(r, "FirebaseStorage-" + mNameSuffix + threadNumber.getAndIncrement()); t.setDaemon(false); diff --git a/tools/lint/src/main/kotlin/CheckRegistry.kt b/tools/lint/src/main/kotlin/CheckRegistry.kt index 4b995e55cb4..15fa532cf14 100644 --- a/tools/lint/src/main/kotlin/CheckRegistry.kt +++ b/tools/lint/src/main/kotlin/CheckRegistry.kt @@ -28,9 +28,8 @@ class CheckRegistry : IssueRegistry() { KotlinInteropDetector.PLATFORM_NULLNESS, NonAndroidxNullabilityDetector.NON_ANDROIDX_NULLABILITY, DeferredApiDetector.INVALID_DEFERRED_API_USE, - ProviderAssignmentDetector.INVALID_PROVIDER_ASSIGNMENT - // TODO(vkryachko): enable the check after suppressing current violations. - // ThreadPoolDetector.THREAD_POOL_CREATION + ProviderAssignmentDetector.INVALID_PROVIDER_ASSIGNMENT, + ThreadPoolDetector.THREAD_POOL_CREATION ) override val api: Int diff --git a/tools/lint/src/main/kotlin/ThreadPoolDetector.kt b/tools/lint/src/main/kotlin/ThreadPoolDetector.kt index 46148b5b0f7..7cd5bc01d6c 100644 --- a/tools/lint/src/main/kotlin/ThreadPoolDetector.kt +++ b/tools/lint/src/main/kotlin/ThreadPoolDetector.kt @@ -22,6 +22,13 @@ class ThreadPoolDetector : Detector(), SourceCodeScanner { "newWorkStealingPool" ) + override fun getApplicableConstructorTypes(): List = listOf( + "java.lang.Thread", + "java.util.concurrent.ForkJoinPool", + "java.util.concurrent.ThreadPoolExecutor", + "java.util.concurrent.ScheduledThreadPoolExecutor" + ) + override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { if (!isExecutorMethod(method)) { return @@ -30,7 +37,20 @@ class ThreadPoolDetector : Detector(), SourceCodeScanner { context.report( THREAD_POOL_CREATION, context.getCallLocation(node, includeReceiver = false, includeArguments = true), - "Creating thread pools is not allowed.") + "Creating thread pools is not allowed." + ) + } + + override fun visitConstructor( + context: JavaContext, + node: UCallExpression, + constructor: PsiMethod + ) { + context.report( + THREAD_POOL_CREATION, + context.getCallLocation(node, includeReceiver = false, includeArguments = true), + "Creating threads or thread pools is not allowed." + ) } private fun isExecutorMethod(method: PsiMethod): Boolean { diff --git a/transport/transport-runtime/src/main/java/com/google/android/datatransport/runtime/ExecutionModule.java b/transport/transport-runtime/src/main/java/com/google/android/datatransport/runtime/ExecutionModule.java index 64eeae96a48..17643e1ee35 100644 --- a/transport/transport-runtime/src/main/java/com/google/android/datatransport/runtime/ExecutionModule.java +++ b/transport/transport-runtime/src/main/java/com/google/android/datatransport/runtime/ExecutionModule.java @@ -14,6 +14,7 @@ package com.google.android.datatransport.runtime; +import android.annotation.SuppressLint; import dagger.Module; import dagger.Provides; import java.util.concurrent.Executor; @@ -24,6 +25,7 @@ abstract class ExecutionModule { @Singleton @Provides + @SuppressLint("ThreadPoolCreation") static Executor executor() { return new SafeLoggingExecutor(Executors.newSingleThreadExecutor()); }