xref: /aosp_15_r20/external/dagger2/java/dagger/hilt/android/EarlyEntryPoints.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2021 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.hilt.android;
18 
19 import android.app.Application;
20 import android.content.Context;
21 import dagger.hilt.EntryPoints;
22 import dagger.hilt.android.internal.Contexts;
23 import dagger.hilt.internal.GeneratedComponentManagerHolder;
24 import dagger.hilt.internal.Preconditions;
25 import dagger.hilt.internal.TestSingletonComponentManager;
26 import dagger.internal.Beta;
27 import java.lang.annotation.Annotation;
28 import javax.annotation.Nonnull;
29 
30 /** Static utility methods for accessing entry points annotated with {@link EarlyEntryPoint}. */
31 @Beta
32 public final class EarlyEntryPoints {
33 
34   /**
35    * Returns the early entry point interface given a component manager holder. Note that this
36    * performs an unsafe cast and so callers should be sure that the given component/component
37    * manager matches the early entry point interface that is given.
38    *
39    * @param applicationContext The application context.
40    * @param entryPoint The interface marked with {@link EarlyEntryPoint}. The {@link
41    *     dagger.hilt.InstallIn} annotation on this entry point should match the component argument
42    *     above.
43    */
44   // Note that the input is not statically declared to be a Component or ComponentManager to make
45   // this method easier to use, since most code will use this with an Application or Context type.
46   @Nonnull
get(Context applicationContext, Class<T> entryPoint)47   public static <T> T get(Context applicationContext, Class<T> entryPoint) {
48     Application application = Contexts.getApplication(applicationContext);
49     Preconditions.checkState(
50         application instanceof GeneratedComponentManagerHolder,
51         "Expected application to implement GeneratedComponentManagerHolder. "
52             + "Check that you're passing in an application context that uses Hilt. "
53             + "Application class found: %s", application.getClass());
54     Object componentManager =
55         ((GeneratedComponentManagerHolder) application).componentManager();
56     if (componentManager instanceof TestSingletonComponentManager) {
57       Preconditions.checkState(
58           hasAnnotationReflection(entryPoint, EarlyEntryPoint.class),
59           "%s should be called with EntryPoints.get() rather than EarlyEntryPoints.get()",
60           entryPoint.getCanonicalName());
61       Object earlyComponent =
62           ((TestSingletonComponentManager) componentManager).earlySingletonComponent();
63       return entryPoint.cast(earlyComponent);
64     }
65 
66     // @EarlyEntryPoint only has an effect in test environment, so if this is not a test we
67     // delegate to EntryPoints.
68     return EntryPoints.get(application, entryPoint);
69   }
70 
71   // Note: This method uses reflection but it should only be called in test environments.
hasAnnotationReflection( Class<?> clazz, Class<? extends Annotation> annotationClazz)72   private static boolean hasAnnotationReflection(
73       Class<?> clazz, Class<? extends Annotation> annotationClazz) {
74     for (Annotation annotation : clazz.getAnnotations()) {
75       if (annotation.annotationType().equals(annotationClazz)) {
76         return true;
77       }
78     }
79     return false;
80   }
81 
EarlyEntryPoints()82   private EarlyEntryPoints() {}
83 }
84