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