1 /* 2 * Copyright 2020 The Android Open Source Project 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 androidx.startup; 18 19 import android.app.Application; 20 import android.content.ContentProvider; 21 import android.content.ContentValues; 22 import android.content.Context; 23 import android.database.Cursor; 24 import android.net.Uri; 25 26 import org.jspecify.annotations.NonNull; 27 import org.jspecify.annotations.Nullable; 28 29 /** 30 * The {@link ContentProvider} which discovers {@link Initializer}s in an application and 31 * initializes them before {@link Application#onCreate()}. 32 */ 33 public class InitializationProvider extends ContentProvider { 34 35 @Override onCreate()36 public final boolean onCreate() { 37 Context context = getContext(); 38 if (context != null) { 39 // Many Initializer's expect the `applicationContext` to be non-null. This 40 // typically happens when `android:sharedUid` is used. In such cases, we postpone 41 // initialization altogether, and rely on lazy init. 42 // More context: b/196959015 43 Context applicationContext = context.getApplicationContext(); 44 if (applicationContext != null) { 45 // Pass the class context so the right metadata can be read. 46 // This is especially important in the context of apps that want to use 47 // InitializationProvider in multiple processes. 48 // b/183136596#comment18 49 AppInitializer.getInstance(context).discoverAndInitialize(getClass()); 50 } else { 51 StartupLogger.w("Deferring initialization because `applicationContext` is null."); 52 } 53 } else { 54 throw new StartupException("Context cannot be null"); 55 } 56 return true; 57 } 58 59 @Override query( @onNull Uri uri, String @Nullable [] projection, @Nullable String selection, String @Nullable [] selectionArgs, @Nullable String sortOrder)60 public final @Nullable Cursor query( 61 @NonNull Uri uri, 62 String @Nullable [] projection, 63 @Nullable String selection, 64 String @Nullable [] selectionArgs, 65 @Nullable String sortOrder) { 66 throw new IllegalStateException("Not allowed."); 67 } 68 69 @Override getType(@onNull Uri uri)70 public final @Nullable String getType(@NonNull Uri uri) { 71 throw new IllegalStateException("Not allowed."); 72 } 73 74 @Override insert(@onNull Uri uri, @Nullable ContentValues values)75 public final @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { 76 throw new IllegalStateException("Not allowed."); 77 } 78 79 @Override delete( @onNull Uri uri, @Nullable String selection, String @Nullable [] selectionArgs)80 public final int delete( 81 @NonNull Uri uri, 82 @Nullable String selection, 83 String @Nullable [] selectionArgs) { 84 throw new IllegalStateException("Not allowed."); 85 } 86 87 @Override update( @onNull Uri uri, @Nullable ContentValues values, @Nullable String selection, String @Nullable [] selectionArgs)88 public final int update( 89 @NonNull Uri uri, 90 @Nullable ContentValues values, 91 @Nullable String selection, 92 String @Nullable [] selectionArgs) { 93 throw new IllegalStateException("Not allowed."); 94 } 95 } 96