diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0ed5aec58924a..a62f0a6807bb1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -75,6 +75,7 @@ import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
+import android.content.res.loader.ResourcesLoader;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDebug;
import android.database.sqlite.SQLiteDebug.DbStats;
@@ -3283,6 +3284,12 @@ public final class ActivityThread extends ClientTransactionHandler {
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
+
+ // Activity resources must be initialized with the same loaders as the
+ // application context.
+ appContext.getResources().addLoaders(
+ app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
+
appContext.setOuterContext(activity);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
@@ -4083,6 +4090,11 @@ public final class ActivityThread extends ClientTransactionHandler {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = packageInfo.getAppFactory()
.instantiateService(cl, data.info.name, data.intent);
+ // Service resources must be initialized with the same loaders as the application
+ // context.
+ context.getResources().addLoaders(
+ app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
+
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
diff --git a/tests/AppResourcesLoaders/Android.bp b/tests/AppResourcesLoaders/Android.bp
new file mode 100644
index 0000000000000..e5739dbf181c4
--- /dev/null
+++ b/tests/AppResourcesLoaders/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
+//
+
+android_test {
+ name: "AppResourcesLoaders",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ java_resources: [":AppResourcesLoaders_Overlay"]
+}
diff --git a/tests/AppResourcesLoaders/AndroidManifest.xml b/tests/AppResourcesLoaders/AndroidManifest.xml
new file mode 100644
index 0000000000000..cb403b968abf7
--- /dev/null
+++ b/tests/AppResourcesLoaders/AndroidManifest.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/AppResourcesLoaders/Overlay/Android.bp b/tests/AppResourcesLoaders/Overlay/Android.bp
new file mode 100644
index 0000000000000..80443f6c3c00a
--- /dev/null
+++ b/tests/AppResourcesLoaders/Overlay/Android.bp
@@ -0,0 +1,19 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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.
+//
+
+android_test_helper_app {
+ name: "AppResourcesLoaders_Overlay",
+}
diff --git a/tests/AppResourcesLoaders/Overlay/AndroidManifest.xml b/tests/AppResourcesLoaders/Overlay/AndroidManifest.xml
new file mode 100644
index 0000000000000..083ba37262fdb
--- /dev/null
+++ b/tests/AppResourcesLoaders/Overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
diff --git a/tests/AppResourcesLoaders/Overlay/res/values/values.xml b/tests/AppResourcesLoaders/Overlay/res/values/values.xml
new file mode 100644
index 0000000000000..8f6e462ffcaef
--- /dev/null
+++ b/tests/AppResourcesLoaders/Overlay/res/values/values.xml
@@ -0,0 +1,20 @@
+
+
+
+ Loaders present: true
+
+
\ No newline at end of file
diff --git a/tests/AppResourcesLoaders/res/layout/activity_isolated.xml b/tests/AppResourcesLoaders/res/layout/activity_isolated.xml
new file mode 100644
index 0000000000000..0a13f00633f65
--- /dev/null
+++ b/tests/AppResourcesLoaders/res/layout/activity_isolated.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/AppResourcesLoaders/res/layout/activity_main.xml b/tests/AppResourcesLoaders/res/layout/activity_main.xml
new file mode 100644
index 0000000000000..7277700cb14cf
--- /dev/null
+++ b/tests/AppResourcesLoaders/res/layout/activity_main.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/AppResourcesLoaders/res/values/styles.xml b/tests/AppResourcesLoaders/res/values/styles.xml
new file mode 100644
index 0000000000000..ee73d65a21a60
--- /dev/null
+++ b/tests/AppResourcesLoaders/res/values/styles.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/AppResourcesLoaders/res/values/values.xml b/tests/AppResourcesLoaders/res/values/values.xml
new file mode 100644
index 0000000000000..af128b6e0ac9d
--- /dev/null
+++ b/tests/AppResourcesLoaders/res/values/values.xml
@@ -0,0 +1,20 @@
+
+
+
+ Loaders present: false
+
+
\ No newline at end of file
diff --git a/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivity.java b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivity.java
new file mode 100644
index 0000000000000..49ef46f1c8de9
--- /dev/null
+++ b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.android.example.loaders;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class LoaderActivity extends Activity {
+
+ @Override
+ protected void attachBaseContext(Context newBase) {
+ super.attachBaseContext(newBase);
+ final String loaderPresentOnAttach =
+ newBase.getResources().getString(R.string.loader_present);
+ if (loaderPresentOnAttach == null || !loaderPresentOnAttach.endsWith("true")) {
+ throw new AssertionError("Loader not present in attachBaseContext");
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ findViewById(R.id.btn_isolated_activity).setOnClickListener((v) -> {
+ startActivity(new Intent(this, LoaderActivityIsolated.class));
+ });
+ }
+}
diff --git a/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivityIsolated.java b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivityIsolated.java
new file mode 100644
index 0000000000000..04550b980ea10
--- /dev/null
+++ b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoaderActivityIsolated.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.android.example.loaders;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+
+public class LoaderActivityIsolated extends Activity {
+
+ @Override
+ protected void attachBaseContext(Context newBase) {
+ super.attachBaseContext(newBase);
+ final String loaderPresentOnAttach =
+ newBase.getResources().getString(R.string.loader_present);
+ if (loaderPresentOnAttach == null || !loaderPresentOnAttach.endsWith("true")) {
+ throw new AssertionError("Loader not present in attachBaseContext");
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_isolated);
+ }
+}
diff --git a/tests/AppResourcesLoaders/src/com/android/example/loaders/LoadersApplication.java b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoadersApplication.java
new file mode 100644
index 0000000000000..709c208f4174f
--- /dev/null
+++ b/tests/AppResourcesLoaders/src/com/android/example/loaders/LoadersApplication.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.android.example.loaders;
+
+import android.app.Application;
+import android.content.res.Resources;
+import android.content.res.loader.ResourcesLoader;
+import android.content.res.loader.ResourcesProvider;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class LoadersApplication extends Application {
+ private static final String TAG = "LoadersApplication";
+ private static final String LOADER_RESOURCES_APK = "AppResourcesLoaders_Overlay.apk";
+
+ @Override
+ public void onCreate() {
+ try {
+ final Resources resources = getResources();
+ final ResourcesLoader loader = new ResourcesLoader();
+ loader.addProvider(ResourcesProvider.loadFromApk(copyResource(LOADER_RESOURCES_APK)));
+ resources.addLoaders(loader);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to load loader resources ", e);
+ }
+ }
+
+ private ParcelFileDescriptor copyResource(String fileName) throws IOException {
+ final File apkFile = new File(getFilesDir(), fileName);
+ final InputStream is = getClassLoader().getResourceAsStream(LOADER_RESOURCES_APK);
+ final FileOutputStream os = new FileOutputStream(apkFile);
+ byte[] buffer = new byte[8192];
+ int count;
+ while ((count = is.read(buffer)) != -1) {
+ os.write(buffer, 0, count);
+ }
+ return ParcelFileDescriptor.open(apkFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ }
+}