Merge "Squash same ApplicationInfo's in Parcel" into rvc-dev am: 9577cd78ff
Change-Id: Idd92356c84cf7d891083f08ee2ac230a740e52c9
This commit is contained in:
@@ -981,6 +981,14 @@ package android.content.pm {
|
||||
field @Nullable public final String backgroundPermission;
|
||||
}
|
||||
|
||||
public final class ProviderInfoList implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public static android.content.pm.ProviderInfoList fromList(@NonNull java.util.List<android.content.pm.ProviderInfo>);
|
||||
method @NonNull public java.util.List<android.content.pm.ProviderInfo> getList();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ProviderInfoList> CREATOR;
|
||||
}
|
||||
|
||||
public final class ShortcutInfo implements android.os.Parcelable {
|
||||
method public boolean isVisibleToPublisher();
|
||||
}
|
||||
@@ -2469,7 +2477,9 @@ package android.os {
|
||||
}
|
||||
|
||||
public final class Parcel {
|
||||
method public boolean allowSquashing();
|
||||
method public int readExceptionCode();
|
||||
method public void restoreAllowSquashing(boolean);
|
||||
}
|
||||
|
||||
public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
|
||||
|
||||
@@ -68,6 +68,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ProviderInfoList;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
@@ -1011,8 +1012,9 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
sendMessage(H.STOP_SERVICE, token);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void bindApplication(String processName, ApplicationInfo appInfo,
|
||||
List<ProviderInfo> providers, ComponentName instrumentationName,
|
||||
ProviderInfoList providerList, ComponentName instrumentationName,
|
||||
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
|
||||
IInstrumentationWatcher instrumentationWatcher,
|
||||
IUiAutomationConnection instrumentationUiConnection, int debugMode,
|
||||
@@ -1052,7 +1054,7 @@ public final class ActivityThread extends ClientTransactionHandler {
|
||||
AppBindData data = new AppBindData();
|
||||
data.processName = processName;
|
||||
data.appInfo = appInfo;
|
||||
data.providers = providers;
|
||||
data.providers = providerList.getList();
|
||||
data.instrumentationName = instrumentationName;
|
||||
data.instrumentationArgs = instrumentationArgs;
|
||||
data.instrumentationWatcher = instrumentationWatcher;
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ProviderInfoList;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
@@ -66,7 +67,7 @@ oneway interface IApplicationThread {
|
||||
@UnsupportedAppUsage
|
||||
void scheduleStopService(IBinder token);
|
||||
void bindApplication(in String packageName, in ApplicationInfo info,
|
||||
in List<ProviderInfo> providers, in ComponentName testName,
|
||||
in ProviderInfoList providerList, in ComponentName testName,
|
||||
in ProfilerInfo profilerInfo, in Bundle testArguments,
|
||||
IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection,
|
||||
int debugMode, boolean enableBinderTracking, boolean trackAllocation,
|
||||
|
||||
@@ -1630,6 +1630,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
if (dest.maybeWriteSquashed(this)) {
|
||||
return;
|
||||
}
|
||||
super.writeToParcel(dest, parcelableFlags);
|
||||
dest.writeString(taskAffinity);
|
||||
dest.writeString(permission);
|
||||
@@ -1700,9 +1703,12 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
|
||||
= new Parcelable.Creator<ApplicationInfo>() {
|
||||
@Override
|
||||
public ApplicationInfo createFromParcel(Parcel source) {
|
||||
return new ApplicationInfo(source);
|
||||
return source.readSquashed(ApplicationInfo::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationInfo[] newArray(int size) {
|
||||
return new ApplicationInfo[size];
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Printer;
|
||||
|
||||
/**
|
||||
@@ -197,12 +196,7 @@ public class ComponentInfo extends PackageItemInfo {
|
||||
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
super.writeToParcel(dest, parcelableFlags);
|
||||
if ((parcelableFlags & Parcelable.PARCELABLE_ELIDE_DUPLICATES) != 0) {
|
||||
dest.writeInt(0);
|
||||
} else {
|
||||
dest.writeInt(1);
|
||||
applicationInfo.writeToParcel(dest, parcelableFlags);
|
||||
}
|
||||
applicationInfo.writeToParcel(dest, parcelableFlags);
|
||||
dest.writeString(processName);
|
||||
dest.writeString(splitName);
|
||||
dest.writeInt(descriptionRes);
|
||||
@@ -213,10 +207,7 @@ public class ComponentInfo extends PackageItemInfo {
|
||||
|
||||
protected ComponentInfo(Parcel source) {
|
||||
super(source);
|
||||
final boolean hasApplicationInfo = (source.readInt() != 0);
|
||||
if (hasApplicationInfo) {
|
||||
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
|
||||
}
|
||||
applicationInfo = ApplicationInfo.CREATOR.createFromParcel(source);
|
||||
processName = source.readString();
|
||||
splitName = source.readString();
|
||||
descriptionRes = source.readInt();
|
||||
|
||||
@@ -439,6 +439,8 @@ public class PackageInfo implements Parcelable {
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
// Allow ApplicationInfo to be squashed.
|
||||
final boolean prevAllowSquashing = dest.allowSquashing();
|
||||
dest.writeString(packageName);
|
||||
dest.writeStringArray(splitNames);
|
||||
dest.writeInt(versionCode);
|
||||
@@ -457,10 +459,10 @@ public class PackageInfo implements Parcelable {
|
||||
dest.writeLong(firstInstallTime);
|
||||
dest.writeLong(lastUpdateTime);
|
||||
dest.writeIntArray(gids);
|
||||
dest.writeTypedArray(activities, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(receivers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(services, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(providers, parcelableFlags | Parcelable.PARCELABLE_ELIDE_DUPLICATES);
|
||||
dest.writeTypedArray(activities, parcelableFlags);
|
||||
dest.writeTypedArray(receivers, parcelableFlags);
|
||||
dest.writeTypedArray(services, parcelableFlags);
|
||||
dest.writeTypedArray(providers, parcelableFlags);
|
||||
dest.writeTypedArray(instrumentation, parcelableFlags);
|
||||
dest.writeTypedArray(permissions, parcelableFlags);
|
||||
dest.writeStringArray(requestedPermissions);
|
||||
@@ -488,6 +490,7 @@ public class PackageInfo implements Parcelable {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeBoolean(isApex);
|
||||
dest.restoreAllowSquashing(prevAllowSquashing);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<PackageInfo> CREATOR
|
||||
@@ -550,21 +553,5 @@ public class PackageInfo implements Parcelable {
|
||||
signingInfo = SigningInfo.CREATOR.createFromParcel(source);
|
||||
}
|
||||
isApex = source.readBoolean();
|
||||
// The component lists were flattened with the redundant ApplicationInfo
|
||||
// instances omitted. Distribute the canonical one here as appropriate.
|
||||
if (applicationInfo != null) {
|
||||
propagateApplicationInfo(applicationInfo, activities);
|
||||
propagateApplicationInfo(applicationInfo, receivers);
|
||||
propagateApplicationInfo(applicationInfo, services);
|
||||
propagateApplicationInfo(applicationInfo, providers);
|
||||
}
|
||||
}
|
||||
|
||||
private void propagateApplicationInfo(ApplicationInfo appInfo, ComponentInfo[] components) {
|
||||
if (components != null) {
|
||||
for (ComponentInfo ci : components) {
|
||||
ci.applicationInfo = appInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
core/java/android/content/pm/ProviderInfoList.aidl
Normal file
19
core/java/android/content/pm/ProviderInfoList.aidl
Normal file
@@ -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.
|
||||
*/
|
||||
|
||||
package android.content.pm;
|
||||
|
||||
parcelable ProviderInfoList;
|
||||
87
core/java/android/content/pm/ProviderInfoList.java
Normal file
87
core/java/android/content/pm/ProviderInfoList.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 android.content.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Equivalent to List<ProviderInfo>, but it "squashes" the ApplicationInfo in the elements.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public final class ProviderInfoList implements Parcelable {
|
||||
private final List<ProviderInfo> mList;
|
||||
|
||||
private ProviderInfoList(Parcel source) {
|
||||
final ArrayList<ProviderInfo> list = new ArrayList<>();
|
||||
source.readTypedList(list, ProviderInfo.CREATOR);
|
||||
mList = list;
|
||||
}
|
||||
|
||||
private ProviderInfoList(List<ProviderInfo> list) {
|
||||
mList = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
// Allow ApplicationInfo to be squashed.
|
||||
final boolean prevAllowSquashing = dest.allowSquashing();
|
||||
dest.writeTypedList(mList, flags);
|
||||
dest.restoreAllowSquashing(prevAllowSquashing);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<ProviderInfoList> CREATOR
|
||||
= new Parcelable.Creator<ProviderInfoList>() {
|
||||
@Override
|
||||
public ProviderInfoList createFromParcel(@NonNull Parcel source) {
|
||||
return new ProviderInfoList(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProviderInfoList[] newArray(int size) {
|
||||
return new ProviderInfoList[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the stored list.
|
||||
*/
|
||||
@NonNull
|
||||
public List<ProviderInfo> getList() {
|
||||
return mList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with a {@code list}. The passed list will be shared with the new
|
||||
* instance, so the caller shouldn't modify it.
|
||||
*/
|
||||
@NonNull
|
||||
public static ProviderInfoList fromList(@NonNull List<ProviderInfo> list) {
|
||||
return new ProviderInfoList(list);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.util.ExceptionUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.SizeF;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
@@ -1826,6 +1827,179 @@ public final class Parcel {
|
||||
writeString(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* A map used by {@link #maybeWriteSquashed} to keep track of what parcelables have
|
||||
* been seen, and what positions they were written. The value is the absolute position of
|
||||
* each parcelable.
|
||||
*/
|
||||
private ArrayMap<Parcelable, Integer> mWrittenSquashableParcelables;
|
||||
|
||||
private void ensureWrittenSquashableParcelables() {
|
||||
if (mWrittenSquashableParcelables != null) {
|
||||
return;
|
||||
}
|
||||
mWrittenSquashableParcelables = new ArrayMap<>();
|
||||
}
|
||||
|
||||
private boolean mAllowSquashing = false;
|
||||
|
||||
/**
|
||||
* Allow "squashing" writes in {@link #maybeWriteSquashed}. This allows subsequent calls to
|
||||
* {@link #maybeWriteSquashed(Parcelable)} to "squash" the same instances into one in a Parcel.
|
||||
*
|
||||
* Typically, this method is called at the beginning of {@link Parcelable#writeToParcel}. The
|
||||
* caller must retain the return value from this method and call {@link #restoreAllowSquashing}
|
||||
* with it.
|
||||
*
|
||||
* See {@link #maybeWriteSquashed(Parcelable)} for the details.
|
||||
*
|
||||
* @see #restoreAllowSquashing(boolean)
|
||||
* @see #maybeWriteSquashed(Parcelable)
|
||||
* @see #readSquashed(SquashReadHelper)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public boolean allowSquashing() {
|
||||
boolean previous = mAllowSquashing;
|
||||
mAllowSquashing = true;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #allowSquashing()
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void restoreAllowSquashing(boolean previous) {
|
||||
mAllowSquashing = previous;
|
||||
if (!mAllowSquashing) {
|
||||
mWrittenSquashableParcelables = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void resetSqaushingState() {
|
||||
if (mAllowSquashing) {
|
||||
Slog.wtf(TAG, "allowSquashing wasn't restored.");
|
||||
}
|
||||
mWrittenSquashableParcelables = null;
|
||||
mReadSquashableParcelables = null;
|
||||
mAllowSquashing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A map used by {@link #readSquashed} to cache parcelables. It's a map from
|
||||
* an absolute position in a Parcel to the parcelable stored at the position.
|
||||
*/
|
||||
private ArrayMap<Integer, Parcelable> mReadSquashableParcelables;
|
||||
|
||||
private void ensureReadSquashableParcelables() {
|
||||
if (mReadSquashableParcelables != null) {
|
||||
return;
|
||||
}
|
||||
mReadSquashableParcelables = new ArrayMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a parcelable with "squash" -- that is, when the same instance is written to the
|
||||
* same Parcelable multiple times, instead of writing the entire instance multiple times,
|
||||
* only write it once, and in subsequent writes we'll only write the offset to the original
|
||||
* object.
|
||||
*
|
||||
* This approach does not work of the resulting Parcel is copied with {@link #appendFrom} with
|
||||
* a non-zero offset, so we do not enable this behavior by default. Instead, we only enable
|
||||
* it between {@link #allowSquashing} and {@link #restoreAllowSquashing}, in order to make sure
|
||||
* we only do so within each "top level" Parcelable.
|
||||
*
|
||||
* Usage: Use this method in {@link Parcelable#writeToParcel}.
|
||||
* If this method returns TRUE, it's a subsequent call, and the offset is already written,
|
||||
* so the caller doesn't have to do anything. If this method returns FALSE, it's the first
|
||||
* time for the instance to be written to this parcel. The caller has to proceed with its
|
||||
* {@link Parcelable#writeToParcel}.
|
||||
*
|
||||
* (See {@code ApplicationInfo} for the example.)
|
||||
*
|
||||
* @param p the target Parcelable to write.
|
||||
*
|
||||
* @see #allowSquashing()
|
||||
* @see #restoreAllowSquashing(boolean)
|
||||
* @see #readSquashed(SquashReadHelper)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public boolean maybeWriteSquashed(@NonNull Parcelable p) {
|
||||
if (!mAllowSquashing) {
|
||||
// Don't squash, and don't put it in the map either.
|
||||
writeInt(0);
|
||||
return false;
|
||||
}
|
||||
ensureWrittenSquashableParcelables();
|
||||
final Integer firstPos = mWrittenSquashableParcelables.get(p);
|
||||
if (firstPos != null) {
|
||||
// Already written.
|
||||
// Write the relative offset from the current position to the first position.
|
||||
final int pos = dataPosition();
|
||||
|
||||
// We want the offset from the next byte of this integer, so we need to +4.
|
||||
writeInt(pos - firstPos + 4);
|
||||
return true;
|
||||
}
|
||||
// First time seen, write a marker.
|
||||
writeInt(0);
|
||||
|
||||
// Remember the position.
|
||||
final int pos = dataPosition();
|
||||
mWrittenSquashableParcelables.put(p, pos);
|
||||
|
||||
// Return false and let the caller actually write the content.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that's used by {@link #readSquashed(SquashReadHelper)}
|
||||
* @hide
|
||||
*/
|
||||
public interface SquashReadHelper<T> {
|
||||
/** Read and instantiate {@code T} from a Parcel. */
|
||||
@NonNull
|
||||
T readRawParceled(@NonNull Parcel p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a {@link Parcelable} that's written with {@link #maybeWriteSquashed}.
|
||||
*
|
||||
* @param reader a callback function that instantiates an instance from a parcel.
|
||||
* Typicallly, a lambda to the instructor that takes a {@link Parcel} is passed.
|
||||
*
|
||||
* @see #maybeWriteSquashed(Parcelable)
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
public <T extends Parcelable> T readSquashed(SquashReadHelper<T> reader) {
|
||||
final int offset = readInt();
|
||||
final int pos = dataPosition();
|
||||
|
||||
if (offset == 0) {
|
||||
// First time read. Unparcel, and remember it.
|
||||
final T p = reader.readRawParceled(this);
|
||||
ensureReadSquashableParcelables();
|
||||
mReadSquashableParcelables.put(pos, p);
|
||||
return p;
|
||||
}
|
||||
// Subsequent read.
|
||||
final int firstAbsolutePos = pos - offset;
|
||||
|
||||
final Parcelable p = mReadSquashableParcelables.get(firstAbsolutePos);
|
||||
if (p == null) {
|
||||
Slog.wtfStack(TAG, "Map doesn't contain offset "
|
||||
+ firstAbsolutePos
|
||||
+ " : contains=" + new ArrayList<>(mReadSquashableParcelables.keySet()));
|
||||
}
|
||||
return (T) p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a generic serializable object in to a Parcel. It is strongly
|
||||
* recommended that this method be avoided, since the serialization
|
||||
@@ -3247,6 +3421,7 @@ public final class Parcel {
|
||||
}
|
||||
|
||||
private void freeBuffer() {
|
||||
resetSqaushingState();
|
||||
if (mOwnsNativeParcelObject) {
|
||||
updateNativeSize(nativeFreeBuffer(mNativePtr));
|
||||
}
|
||||
@@ -3254,6 +3429,7 @@ public final class Parcel {
|
||||
}
|
||||
|
||||
private void destroy() {
|
||||
resetSqaushingState();
|
||||
if (mNativePtr != 0) {
|
||||
if (mOwnsNativeParcelObject) {
|
||||
nativeDestroy(mNativePtr);
|
||||
@@ -3261,7 +3437,6 @@ public final class Parcel {
|
||||
}
|
||||
mNativePtr = 0;
|
||||
}
|
||||
mReadWriteHelper = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ProviderInfoList;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
import android.content.res.Configuration;
|
||||
@@ -397,7 +398,7 @@ public class TransactionParcelTests {
|
||||
|
||||
@Override
|
||||
public void bindApplication(String s, ApplicationInfo applicationInfo,
|
||||
List<ProviderInfo> list, ComponentName componentName, ProfilerInfo profilerInfo,
|
||||
ProviderInfoList list, ComponentName componentName, ProfilerInfo profilerInfo,
|
||||
Bundle bundle, IInstrumentationWatcher iInstrumentationWatcher,
|
||||
IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
|
||||
boolean b2, boolean b3, Configuration configuration,
|
||||
|
||||
@@ -218,6 +218,7 @@ import android.content.pm.PathPermission;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.content.pm.ProcessInfo;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ProviderInfoList;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.SELinuxUtil;
|
||||
import android.content.pm.ServiceInfo;
|
||||
@@ -5151,12 +5152,13 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
if (mPlatformCompat != null) {
|
||||
mPlatformCompat.resetReporting(app.info);
|
||||
}
|
||||
final ProviderInfoList providerList = ProviderInfoList.fromList(providers);
|
||||
if (app.isolatedEntryPoint != null) {
|
||||
// This is an isolated process which should just call an entry point instead of
|
||||
// being bound to an application.
|
||||
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
|
||||
} else if (instr2 != null) {
|
||||
thread.bindApplication(processName, appInfo, providers,
|
||||
thread.bindApplication(processName, appInfo, providerList,
|
||||
instr2.mClass,
|
||||
profilerInfo, instr2.mArguments,
|
||||
instr2.mWatcher,
|
||||
@@ -5169,7 +5171,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
buildSerial, autofillOptions, contentCaptureOptions,
|
||||
app.mDisabledCompatChanges);
|
||||
} else {
|
||||
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
|
||||
thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
|
||||
null, null, null, testMode,
|
||||
mBinderTransactionTrackingEnabled, enableTrackAllocation,
|
||||
isRestrictedBackupMode || !normalMode, app.isPersistent(),
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.AuxiliaryResolveInfo;
|
||||
import android.content.pm.InstantAppResolveInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -272,6 +273,9 @@ public class ComponentResolver {
|
||||
return null;
|
||||
}
|
||||
List<ProviderInfo> providerList = null;
|
||||
|
||||
// Map from a package name to the corresponding app info.
|
||||
ArrayMap<String, ApplicationInfo> appInfos = null;
|
||||
synchronized (mLock) {
|
||||
for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
|
||||
final ParsedProvider p = mProviders.mProviders.valueAt(i);
|
||||
@@ -300,8 +304,29 @@ public class ComponentResolver {
|
||||
&& (p.getMetaData() == null || !p.getMetaData().containsKey(metaDataKey))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure we have AppInfo for this provider.
|
||||
final PackageUserState state = ps.readUserState(userId);
|
||||
ApplicationInfo appInfo =
|
||||
(appInfos == null) ? null : appInfos.get(pkg.getPackageName());
|
||||
if (appInfo == null) {
|
||||
appInfo = PackageInfoUtils.generateApplicationInfo(
|
||||
pkg, flags, state, userId, ps);
|
||||
if (appInfo == null) {
|
||||
// In this case, we should avoid calling generateApplicationInfo() for
|
||||
// the same package in subsequent iterations, but appInfo shouldn't be null
|
||||
// here, so we don't bother.
|
||||
continue;
|
||||
}
|
||||
if (appInfos == null) {
|
||||
appInfos = new ArrayMap<>(4);
|
||||
}
|
||||
appInfos.put(pkg.getPackageName(), appInfo);
|
||||
}
|
||||
// At this point, appInfo != null.
|
||||
|
||||
final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
|
||||
pkg, p, flags, ps.readUserState(userId), userId, ps);
|
||||
pkg, p, flags, state, appInfo, userId, ps);
|
||||
if (info == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -312,8 +312,14 @@ public class PackageInfoUtils {
|
||||
|
||||
/**
|
||||
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
|
||||
*
|
||||
* @deprecated use {@link #generateProviderInfo(
|
||||
* AndroidPackage, ParsedProvider, int, PackageUserState, ApplicationInfo, int, PackageSetting)}
|
||||
* instead and pass {@link ApplicationInfo} explicitly to avoid generating duplicate instances
|
||||
* of it.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
|
||||
@PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
|
||||
@Nullable PackageSetting pkgSetting) {
|
||||
@@ -324,7 +330,7 @@ public class PackageInfoUtils {
|
||||
* @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
|
||||
*/
|
||||
@Nullable
|
||||
private static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
|
||||
public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
|
||||
@PackageManager.ComponentInfoFlags int flags, PackageUserState state,
|
||||
@Nullable ApplicationInfo applicationInfo, int userId,
|
||||
@Nullable PackageSetting pkgSetting) {
|
||||
|
||||
@@ -430,13 +430,6 @@ public class PackageParserTest {
|
||||
ParsedProvider b
|
||||
) {
|
||||
assertComponentsEqual(a, b);
|
||||
|
||||
// Sanity check for ProviderInfo
|
||||
ProviderInfo aInfo = PackageInfoUtils.generateProviderInfo(aPkg, a, 0,
|
||||
new PackageUserState(), 0, mockPkgSetting(aPkg));
|
||||
ProviderInfo bInfo = PackageInfoUtils.generateProviderInfo(bPkg, b, 0,
|
||||
new PackageUserState(), 0, mockPkgSetting(bPkg));
|
||||
assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo);
|
||||
assertEquals(a.getName(), b.getName());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user