Skip to content

Commit 0930b41

Browse files
vkryachkoDavid Motsonashvili
authored and
David Motsonashvili
committed
Merge executors to master (#4322)
* Add qualifier support to firebase components. (#3180) * Add qualifier support to firebase components. Details: go/firebase-component-qualifiers * fix errorprone error. * change copyright year. * Register executors as components. (#4288) * Register executors as components. The intent for those is to be used by all Firebase SDKs and forbid creating their own at will. * Add copyrights. * add more copyrights * ktlintformat * gJF * ktlint * Address review comments. * Adds generally useful executors (#4305) Namely, SequentialExecutor and directExecutor. * Enable strict mode for executors. (#4303) Any violations would kill the app in debug builds of firebase-common, and log a warning in release builds. This is done to fail tests that incorrectly use executors while not affecting 3p apps in release builds. Additionally correctly set thread priorities in an Android specific way. * Enable thread pool linter check. (#4297) * Enable thread pool linter check. All violations are now suppressed, bugs filed to fix each product. * ktlint * Remove init * Fix copyright
1 parent 53efe73 commit 0930b41

File tree

79 files changed

+2030
-152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2030
-152
lines changed

appcheck/firebase-appcheck-debug/src/main/java/com/google/firebase/appcheck/debug/internal/DebugAppCheckProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static com.google.android.gms.common.internal.Preconditions.checkNotNull;
1818

19+
import android.annotation.SuppressLint;
1920
import android.util.Log;
2021
import androidx.annotation.NonNull;
2122
import androidx.annotation.Nullable;
@@ -45,6 +46,8 @@ public class DebugAppCheckProvider implements AppCheckProvider {
4546
private final RetryManager retryManager;
4647
private final Task<String> debugSecretTask;
4748

49+
// TODO(b/258273630): Migrate to go/firebase-android-executors
50+
@SuppressLint("ThreadPoolCreation")
4851
public DebugAppCheckProvider(@NonNull FirebaseApp firebaseApp, @Nullable String debugSecret) {
4952
checkNotNull(firebaseApp);
5053
this.networkClient = new NetworkClient(firebaseApp);

appcheck/firebase-appcheck-playintegrity/src/main/java/com/google/firebase/appcheck/playintegrity/internal/PlayIntegrityAppCheckProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.firebase.appcheck.playintegrity.internal;
1616

17+
import android.annotation.SuppressLint;
1718
import androidx.annotation.NonNull;
1819
import androidx.annotation.VisibleForTesting;
1920
import com.google.android.gms.tasks.Task;
@@ -41,6 +42,8 @@ public class PlayIntegrityAppCheckProvider implements AppCheckProvider {
4142
private final ExecutorService backgroundExecutor;
4243
private final RetryManager retryManager;
4344

45+
// TODO(b/258273630): Migrate to go/firebase-android-executors
46+
@SuppressLint("ThreadPoolCreation")
4447
public PlayIntegrityAppCheckProvider(@NonNull FirebaseApp firebaseApp) {
4548
this(
4649
firebaseApp.getOptions().getGcmSenderId(),

appcheck/firebase-appcheck-safetynet/src/main/java/com/google/firebase/appcheck/safetynet/internal/SafetyNetAppCheckProvider.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static com.google.android.gms.common.internal.Preconditions.checkNotEmpty;
1818
import static com.google.android.gms.common.internal.Preconditions.checkNotNull;
1919

20+
import android.annotation.SuppressLint;
2021
import android.content.Context;
2122
import androidx.annotation.NonNull;
2223
import androidx.annotation.VisibleForTesting;
@@ -56,6 +57,8 @@ public class SafetyNetAppCheckProvider implements AppCheckProvider {
5657
private final String apiKey;
5758

5859
/** @param firebaseApp the FirebaseApp to which this Factory is tied. */
60+
// TODO(b/258273630): Migrate to go/firebase-android-executors
61+
@SuppressLint("ThreadPoolCreation")
5962
public SafetyNetAppCheckProvider(@NonNull FirebaseApp firebaseApp) {
6063
this(
6164
firebaseApp,

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultFirebaseAppCheck.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static com.google.android.gms.common.internal.Preconditions.checkNotNull;
1818

19+
import android.annotation.SuppressLint;
1920
import androidx.annotation.NonNull;
2021
import androidx.annotation.Nullable;
2122
import androidx.annotation.VisibleForTesting;
@@ -57,6 +58,8 @@ public class DefaultFirebaseAppCheck extends FirebaseAppCheck {
5758
private AppCheckProvider appCheckProvider;
5859
private AppCheckToken cachedToken;
5960

61+
// TODO(b/258273630): Migrate to go/firebase-android-executors
62+
@SuppressLint("ThreadPoolCreation")
6063
public DefaultFirebaseAppCheck(
6164
@NonNull FirebaseApp firebaseApp,
6265
@NonNull Provider<HeartBeatController> heartBeatController) {

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/internal/DefaultTokenRefresher.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static java.util.concurrent.TimeUnit.MILLISECONDS;
1919
import static java.util.concurrent.TimeUnit.SECONDS;
2020

21+
import android.annotation.SuppressLint;
2122
import androidx.annotation.NonNull;
2223
import androidx.annotation.VisibleForTesting;
2324
import com.google.android.gms.tasks.OnFailureListener;
@@ -41,6 +42,8 @@ public class DefaultTokenRefresher {
4142
private volatile ScheduledFuture<?> refreshFuture;
4243
private volatile long delayAfterFailureSeconds;
4344

45+
// TODO(b/258273630): Migrate to go/firebase-android-executors
46+
@SuppressLint("ThreadPoolCreation")
4447
DefaultTokenRefresher(@NonNull DefaultFirebaseAppCheck firebaseAppCheck) {
4548
this(checkNotNull(firebaseAppCheck), Executors.newScheduledThreadPool(/* corePoolSize= */ 1));
4649
}

firebase-annotations/firebase-annotations.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,7 @@ java {
2929
tasks.withType(JavaCompile) {
3030
options.compilerArgs << "-Werror"
3131
}
32+
33+
dependencies {
34+
implementation 'javax.inject:javax.inject:1'
35+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.annotations.concurrent;
16+
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Target;
19+
import javax.inject.Qualifier;
20+
21+
/**
22+
* An executor/coroutine dispatcher for long running tasks including disk IO, heavy CPU
23+
* computations.
24+
*
25+
* <p>For operations that can block for long periods of time, like network requests, use the {@link
26+
* Blocking} executor.
27+
*/
28+
@Qualifier
29+
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
30+
public @interface Background {}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.annotations.concurrent;
16+
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Target;
19+
import javax.inject.Qualifier;
20+
21+
/**
22+
* An executor/coroutine dispatcher for tasks that can block for long periods of time, e.g network
23+
* IO.
24+
*/
25+
@Qualifier
26+
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
27+
public @interface Blocking {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.annotations.concurrent;
16+
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Target;
19+
import javax.inject.Qualifier;
20+
21+
/**
22+
* An executor/coroutine dispatcher for lightweight tasks that never block (on IO or other tasks).
23+
*/
24+
@Qualifier
25+
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
26+
public @interface Lightweight {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.annotations.concurrent;
16+
17+
import java.lang.annotation.ElementType;
18+
import java.lang.annotation.Target;
19+
import javax.inject.Qualifier;
20+
21+
/** An executor/coroutine dispatcher for work that must run on the UI thread. */
22+
@Qualifier
23+
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
24+
public @interface UiThread {}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/AabUpdater.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.firebase.appdistribution.impl.TaskUtils.runAsyncInTask;
2020
import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskException;
2121

22+
import android.annotation.SuppressLint;
2223
import android.app.Activity;
2324
import android.content.Intent;
2425
import android.net.Uri;
@@ -52,6 +53,8 @@ class AabUpdater {
5253
@GuardedBy("updateAabLock")
5354
private boolean hasBeenSentToPlayForCurrentTask = false;
5455

56+
// TODO(b/258264924): Migrate to go/firebase-android-executors
57+
@SuppressLint("ThreadPoolCreation")
5558
AabUpdater() {
5659
this(
5760
FirebaseAppDistributionLifecycleNotifier.getInstance(),

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ApkUpdater.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskException;
2020
import static com.google.firebase.appdistribution.impl.TaskUtils.safeSetTaskResult;
2121

22+
import android.annotation.SuppressLint;
2223
import android.content.Context;
2324
import android.os.Build.VERSION;
2425
import android.os.Build.VERSION_CODES;
@@ -62,6 +63,8 @@ class ApkUpdater {
6263

6364
private final Object updateTaskLock = new Object();
6465

66+
// TODO(b/258264924): Migrate to go/firebase-android-executors
67+
@SuppressLint("ThreadPoolCreation")
6568
public ApkUpdater(@NonNull FirebaseApp firebaseApp, @NonNull ApkInstaller apkInstaller) {
6669
this(
6770
Executors.newSingleThreadExecutor(),

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FirebaseAppDistributionTesterApiClient.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import static com.google.firebase.appdistribution.impl.TaskUtils.runAsyncInTask;
1818

19+
import android.annotation.SuppressLint;
1920
import androidx.annotation.NonNull;
2021
import com.google.android.gms.tasks.Task;
2122
import com.google.android.gms.tasks.Tasks;
@@ -63,6 +64,9 @@ private interface FidDependentJob<TResult> {
6364
private final FirebaseApp firebaseApp;
6465
private final Provider<FirebaseInstallationsApi> firebaseInstallationsApiProvider;
6566
private final TesterApiHttpClient testerApiHttpClient;
67+
68+
// TODO(b/258264924): Migrate to go/firebase-android-executors
69+
@SuppressLint("ThreadPoolCreation")
6670
private final Executor taskExecutor = Executors.newSingleThreadExecutor();
6771

6872
FirebaseAppDistributionTesterApiClient(

firebase-common/firebase-common.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ android {
6262
}
6363

6464
dependencies {
65-
// TODO(vkryachko): have sdks depend on components directly once components are released.
65+
implementation project(':firebase-annotations')
6666
implementation project(':firebase-components')
6767
implementation 'com.google.android.gms:play-services-basement:18.1.0'
6868
implementation "com.google.android.gms:play-services-tasks:18.0.1"
69+
implementation 'androidx.concurrent:concurrent-futures:1.1.0'
6970

7071
// FirebaseApp references storage, so storage needs to be on classpath when dokka runs.
7172
javadocClasspath project(path: ':firebase-storage')

firebase-common/ktx/ktx.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ android {
3838
dependencies {
3939
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
4040

41+
implementation project(':firebase-annotations')
4142
implementation project(':firebase-common')
4243
implementation project(':firebase-components')
4344
implementation 'androidx.annotation:annotation:1.1.0'

firebase-common/ktx/src/main/kotlin/com/google/firebase/ktx/Firebase.kt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ import android.content.Context
1717
import androidx.annotation.Keep
1818
import com.google.firebase.FirebaseApp
1919
import com.google.firebase.FirebaseOptions
20+
import com.google.firebase.annotations.concurrent.Background
21+
import com.google.firebase.annotations.concurrent.Blocking
22+
import com.google.firebase.annotations.concurrent.Lightweight
23+
import com.google.firebase.annotations.concurrent.UiThread
2024
import com.google.firebase.components.Component
2125
import com.google.firebase.components.ComponentRegistrar
26+
import com.google.firebase.components.Dependency
27+
import com.google.firebase.components.Qualified
2228
import com.google.firebase.platforminfo.LibraryVersionComponent
29+
import java.util.concurrent.Executor
30+
import kotlinx.coroutines.CoroutineDispatcher
31+
import kotlinx.coroutines.asCoroutineDispatcher
2332

2433
/**
2534
* Single access point to all firebase SDKs from Kotlin.
@@ -56,6 +65,20 @@ internal const val LIBRARY_NAME: String = "fire-core-ktx"
5665
@Keep
5766
class FirebaseCommonKtxRegistrar : ComponentRegistrar {
5867
override fun getComponents(): List<Component<*>> {
59-
return listOf(LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME))
68+
return listOf(
69+
LibraryVersionComponent.create(LIBRARY_NAME, BuildConfig.VERSION_NAME),
70+
coroutineDispatcher<Background>(),
71+
coroutineDispatcher<Lightweight>(),
72+
coroutineDispatcher<Blocking>(),
73+
coroutineDispatcher<UiThread>()
74+
)
6075
}
6176
}
77+
78+
private inline fun <reified T : Annotation> coroutineDispatcher(): Component<CoroutineDispatcher> =
79+
Component.builder(Qualified.qualified(T::class.java, CoroutineDispatcher::class.java))
80+
.add(Dependency.required(Qualified.qualified(T::class.java, Executor::class.java)))
81+
.factory { c ->
82+
c.get(Qualified.qualified(T::class.java, Executor::class.java)).asCoroutineDispatcher()
83+
}
84+
.build()

firebase-common/src/main/java/com/google/firebase/FirebaseApp.java

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import android.content.Intent;
2424
import android.content.IntentFilter;
2525
import android.os.Build;
26-
import android.os.Handler;
27-
import android.os.Looper;
2826
import android.text.TextUtils;
2927
import android.util.Log;
3028
import androidx.annotation.GuardedBy;
@@ -47,6 +45,7 @@
4745
import com.google.firebase.components.ComponentRegistrar;
4846
import com.google.firebase.components.ComponentRuntime;
4947
import com.google.firebase.components.Lazy;
48+
import com.google.firebase.concurrent.ExecutorsRegistrar;
5049
import com.google.firebase.events.Publisher;
5150
import com.google.firebase.heartbeatinfo.DefaultHeartBeatController;
5251
import com.google.firebase.inject.Provider;
@@ -59,7 +58,6 @@
5958
import java.util.List;
6059
import java.util.Map;
6160
import java.util.concurrent.CopyOnWriteArrayList;
62-
import java.util.concurrent.Executor;
6361
import java.util.concurrent.atomic.AtomicBoolean;
6462
import java.util.concurrent.atomic.AtomicReference;
6563

@@ -97,16 +95,10 @@ public class FirebaseApp {
9795

9896
private static final Object LOCK = new Object();
9997

100-
private static final Executor UI_EXECUTOR = new UiExecutor();
101-
10298
/** A map of (name, FirebaseApp) instances. */
10399
@GuardedBy("LOCK")
104100
static final Map<String, FirebaseApp> INSTANCES = new ArrayMap<>();
105101

106-
private static final String FIREBASE_ANDROID = "fire-android";
107-
private static final String FIREBASE_COMMON = "fire-core";
108-
private static final String KOTLIN = "kotlin";
109-
110102
private final Context applicationContext;
111103
private final String name;
112104
private final FirebaseOptions options;
@@ -427,9 +419,10 @@ protected FirebaseApp(Context applicationContext, String name, FirebaseOptions o
427419

428420
FirebaseTrace.pushTrace("Runtime");
429421
componentRuntime =
430-
ComponentRuntime.builder(UI_EXECUTOR)
422+
ComponentRuntime.builder(com.google.firebase.concurrent.UiExecutor.INSTANCE)
431423
.addLazyComponentRegistrars(registrars)
432424
.addComponentRegistrar(new FirebaseCommonRegistrar())
425+
.addComponentRegistrar(new ExecutorsRegistrar())
433426
.addComponent(Component.of(applicationContext, Context.class))
434427
.addComponent(Component.of(this, FirebaseApp.class))
435428
.addComponent(Component.of(options, FirebaseOptions.class))
@@ -712,14 +705,4 @@ public void onBackgroundStateChanged(boolean background) {
712705
}
713706
}
714707
}
715-
716-
private static class UiExecutor implements Executor {
717-
718-
private static final Handler HANDLER = new Handler(Looper.getMainLooper());
719-
720-
@Override
721-
public void execute(@NonNull Runnable command) {
722-
HANDLER.post(command);
723-
}
724-
}
725708
}

0 commit comments

Comments
 (0)