Merge "Check if APK paths are valid right before creating the context." into sc-v2-dev

This commit is contained in:
TreeHugger Robot
2021-10-25 12:26:27 +00:00
committed by Android (Google) Code Review
4 changed files with 47 additions and 7 deletions

View File

@@ -2134,4 +2134,38 @@ public final class LoadedApk {
final IBinder mService; final IBinder mService;
} }
} }
/**
* Check if the Apk paths in the cache are correct, and update them if they are not.
* @hide
*/
public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
// Get the LoadedApk from the cache
ActivityThread activityThread = ActivityThread.currentActivityThread();
if (activityThread == null) {
Log.e(TAG, "Cannot find activity thread");
return;
}
checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
}
private static void checkAndUpdateApkPaths(ActivityThread activityThread,
ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
String expectedCodePath = expectedAppInfo.getCodePath();
LoadedApk loadedApk = activityThread.peekPackageInfo(
expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
// If there is load apk cached, or if the cache is valid, don't do anything.
if (loadedApk == null || loadedApk.getApplicationInfo() == null
|| loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
return;
}
// Duplicate framework logic
List<String> oldPaths = new ArrayList<>();
LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);
// Force update the LoadedApk instance, which should update the reference in the cache
loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
}
} }

View File

@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.LoadedApk;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
@@ -554,7 +555,7 @@ public class AppWidgetHostView extends FrameLayout {
} }
// Prepare a local reference to the remote Context so we're ready to // Prepare a local reference to the remote Context so we're ready to
// inflate any requested LayoutParams. // inflate any requested LayoutParams.
mRemoteContext = getRemoteContext(); mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
int layoutId = rvToApply.getLayoutId(); int layoutId = rvToApply.getLayoutId();
if (rvToApply.canRecycleView(mView)) { if (rvToApply.canRecycleView(mView)) {
@@ -616,7 +617,7 @@ public class AppWidgetHostView extends FrameLayout {
private void inflateAsync(@NonNull RemoteViews remoteViews) { private void inflateAsync(@NonNull RemoteViews remoteViews) {
// Prepare a local reference to the remote Context so we're ready to // Prepare a local reference to the remote Context so we're ready to
// inflate any requested LayoutParams. // inflate any requested LayoutParams.
mRemoteContext = getRemoteContext(); mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
int layoutId = remoteViews.getLayoutId(); int layoutId = remoteViews.getLayoutId();
if (mLastExecutionSignal != null) { if (mLastExecutionSignal != null) {
@@ -718,8 +719,10 @@ public class AppWidgetHostView extends FrameLayout {
* purposes of reading remote resources. * purposes of reading remote resources.
* @hide * @hide
*/ */
protected Context getRemoteContext() { protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
try { try {
ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;
LoadedApk.checkAndUpdateApkPaths(expectedAppInfo);
// Return if cloned successfully, otherwise default // Return if cloned successfully, otherwise default
Context newContext = mContext.createApplicationContext( Context newContext = mContext.createApplicationContext(
mInfo.providerInfo.applicationInfo, mInfo.providerInfo.applicationInfo,
@@ -765,7 +768,7 @@ public class AppWidgetHostView extends FrameLayout {
try { try {
if (mInfo != null) { if (mInfo != null) {
Context theirContext = getRemoteContext(); Context theirContext = getRemoteContextEnsuringCorrectCachedApkPath();
mRemoteContext = theirContext; mRemoteContext = theirContext;
LayoutInflater inflater = (LayoutInflater) LayoutInflater inflater = (LayoutInflater)
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View File

@@ -34,6 +34,7 @@ import android.app.Activity;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.app.ActivityThread; import android.app.ActivityThread;
import android.app.Application; import android.app.Application;
import android.app.LoadedApk;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.RemoteInput; import android.app.RemoteInput;
import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetHostView;
@@ -5475,7 +5476,8 @@ public class RemoteViews implements Parcelable, Filter {
// user. So build a context that loads resources from that user but // user. So build a context that loads resources from that user but
// still returns the current users userId so settings like data / time formats // still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions. // are loaded without requiring cross user persmissions.
final Context contextForResources = getContextForResources(context); final Context contextForResources =
getContextForResourcesEnsuringCorrectCachedApkPaths(context);
if (colorResources != null) { if (colorResources != null) {
colorResources.apply(contextForResources); colorResources.apply(contextForResources);
} }
@@ -5853,13 +5855,14 @@ public class RemoteViews implements Parcelable, Filter {
} }
} }
private Context getContextForResources(Context context) { private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) {
if (mApplication != null) { if (mApplication != null) {
if (context.getUserId() == UserHandle.getUserId(mApplication.uid) if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
&& context.getPackageName().equals(mApplication.packageName)) { && context.getPackageName().equals(mApplication.packageName)) {
return context; return context;
} }
try { try {
LoadedApk.checkAndUpdateApkPaths(mApplication);
return context.createApplicationContext(mApplication, return context.createApplicationContext(mApplication,
Context.CONTEXT_RESTRICTED); Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) { } catch (NameNotFoundException e) {

View File

@@ -408,7 +408,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
} }
@Override @Override
protected Context getRemoteContext() { protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
return null; return null;
} }