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

View File

@@ -34,6 +34,7 @@ import android.app.Activity;
import android.app.ActivityOptions;
import android.app.ActivityThread;
import android.app.Application;
import android.app.LoadedApk;
import android.app.PendingIntent;
import android.app.RemoteInput;
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
// still returns the current users userId so settings like data / time formats
// are loaded without requiring cross user persmissions.
final Context contextForResources = getContextForResources(context);
final Context contextForResources =
getContextForResourcesEnsuringCorrectCachedApkPaths(context);
if (colorResources != null) {
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 (context.getUserId() == UserHandle.getUserId(mApplication.uid)
&& context.getPackageName().equals(mApplication.packageName)) {
return context;
}
try {
LoadedApk.checkAndUpdateApkPaths(mApplication);
return context.createApplicationContext(mApplication,
Context.CONTEXT_RESTRICTED);
} catch (NameNotFoundException e) {

View File

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