Merge "Check if APK paths are valid right before creating the context." into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
cff5e32516
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -408,7 +408,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Context getRemoteContext() {
|
||||
protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user