Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6bef72db authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge changes from topic "per-process-app-class-2"

* changes:
  Support per-process Application class (AM and client side)
  Support per-process Application class (package parser)
  Support per-process Application class in <process> tag
parents fc61bed0 19f22d59
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1352,7 +1352,9 @@ public final class LoadedApk {

        Application app = null;

        String appClass = mApplicationInfo.className;
        final String myProcessName = Process.myProcessName();
        String appClass = mApplicationInfo.getCustomApplicationClassNameForProcess(
                myProcessName);
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }
+65 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.util.ArrayMap;
import android.util.Printer;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -1533,6 +1534,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {

    private int mHiddenApiPolicy = HIDDEN_API_ENFORCEMENT_DEFAULT;

    /**
     * A map from a process name to an (custom) application class name in this package, derived
     * from the <processes> tag in the app's manifest. This map may not contain all the process
     * names. Processses not in this map will use the default app class name,
     * which is {@link #className}, or the default class {@link android.app.Application}.
     */
    @Nullable
    private ArrayMap<String, String> mAppClassNamesByProcess;

    public void dump(Printer pw, String prefix) {
        dump(pw, prefix, DUMP_FLAG_ALL);
    }
@@ -1540,9 +1550,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    /** @hide */
    public void dump(Printer pw, String prefix, int dumpFlags) {
        super.dumpFront(pw, prefix);
        if ((dumpFlags & DUMP_FLAG_DETAILS) != 0 && className != null) {
        if ((dumpFlags & DUMP_FLAG_DETAILS) != 0) {
            if (className != null) {
                pw.println(prefix + "className=" + className);
            }
            for (int i = 0; i < ArrayUtils.size(mAppClassNamesByProcess); i++) {
                pw.println(prefix + "  process=" + mAppClassNamesByProcess.keyAt(i)
                        + " className=" + mAppClassNamesByProcess.valueAt(i));
            }
        }
        if (permission != null) {
            pw.println(prefix + "permission=" + permission);
        }
@@ -1967,6 +1983,16 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        dest.writeInt(nativeHeapZeroInitialized);
        sForBoolean.parcel(requestRawExternalStorageAccess, dest, parcelableFlags);
        dest.writeLong(createTimestamp);
        if (mAppClassNamesByProcess == null) {
            dest.writeInt(0);
        } else {
            final int size = mAppClassNamesByProcess.size();
            dest.writeInt(size);
            for (int i = 0; i < size; i++) {
                dest.writeString(mAppClassNamesByProcess.keyAt(i));
                dest.writeString(mAppClassNamesByProcess.valueAt(i));
            }
        }
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ApplicationInfo> CREATOR
@@ -2055,6 +2081,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        nativeHeapZeroInitialized = source.readInt();
        requestRawExternalStorageAccess = sForBoolean.unparcel(source);
        createTimestamp = source.readLong();
        final int allClassesSize = source.readInt();
        if (allClassesSize > 0) {
            mAppClassNamesByProcess = new ArrayMap<>(allClassesSize);
            for (int i = 0; i < allClassesSize; i++) {
                mAppClassNamesByProcess.put(source.readString(), source.readString());
            }
        }
    }

    /**
@@ -2538,6 +2571,19 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
        requestRawExternalStorageAccess = value;
    }

    /**
     * Replaces {@link #mAppClassNamesByProcess}. This takes over the ownership of the passed map.
     * Do not modify the argument at the callsite.
     * {@hide}
     */
    public void setAppClassNamesByProcess(@Nullable ArrayMap<String, String> value) {
        if (ArrayUtils.size(value) == 0) {
            mAppClassNamesByProcess = null;
        } else {
            mAppClassNamesByProcess = value;
        }
    }

    /** {@hide} */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public String getCodePath() { return scanSourceDir; }
@@ -2568,4 +2614,21 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
    public int getNativeHeapZeroInitialized() {
        return nativeHeapZeroInitialized;
    }

    /**
     * Return the application class name defined in the manifest. The class name set in the
     * <processes> tag for this process, then return it. Otherwise it'll return the class
     * name set in the <application> tag. If neither is set, it'll return null.
     * @hide
     */
    @Nullable
    public String getCustomApplicationClassNameForProcess(String processName) {
        if (mAppClassNamesByProcess != null) {
            String byProcess = mAppClassNamesByProcess.get(processName);
            if (byProcess != null) {
                return byProcess;
            }
        }
        return className;
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ public interface ParsingPackage extends ParsingPackageRead {

    ParsingPackage addQueriesProvider(String authority);

    /** Sets a process name -> {@link ParsedProcess} map coming from the <processes> tag. */
    ParsingPackage setProcesses(@NonNull Map<String, ParsedProcess> processes);

    ParsingPackage asSplit(
+40 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.util.SparseArray;
@@ -297,6 +298,9 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
//    @DataClass.ParcelWith(ParsingUtils.StringPairListParceler.class)
    private List<Pair<String, ParsedIntentInfo>> preferredActivityFilters = emptyList();

    /**
     * Map from a process name to a {@link ParsedProcess}.
     */
    @NonNull
    private Map<String, ParsedProcess> processes = emptyMap();

@@ -1131,10 +1135,46 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
        appInfo.setSplitCodePaths(splitCodePaths);
        appInfo.setSplitResourcePaths(splitCodePaths);
        appInfo.setVersionCode(mLongVersionCode);
        appInfo.setAppClassNamesByProcess(buildAppClassNamesByProcess());

        return appInfo;
    }

    /**
     * Create a map from a process name to the custom application class for this process,
     * which comes from <processes><process android:name="xxx">.
     *
     * The original information is stored in {@link #processes}, but it's stored in
     * a form of: [process name] -[1:N]-> [package name] -[1:N]-> [class name].
     * We scan it and collect the process names and their app class names, only for this package.
     *
     * The resulting map only contains processes with a custom application class set.
     */
    @Nullable
    private ArrayMap<String, String> buildAppClassNamesByProcess() {
        if (processes == null) {
            return null;
        }
        final ArrayMap<String, String> ret = new ArrayMap<>(4);
        for (String processName : processes.keySet()) {
            final ParsedProcess process = processes.get(processName);
            final ArrayMap<String, String> appClassesByPackage =
                    process.getAppClassNamesByPackage();

            for (int i = 0; i < appClassesByPackage.size(); i++) {
                final String packageName = appClassesByPackage.keyAt(i);

                if (this.packageName.equals(packageName)) {
                    final String appClassName = appClassesByPackage.valueAt(i);
                    if (!TextUtils.isEmpty(appClassName)) {
                        ret.put(processName, appClassName);
                    }
                }
            }
        }
        return ret;
    }

    @Override
    public int describeContents() {
        return 0;
+10 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.content.pm.parsing.component;
import android.annotation.NonNull;
import android.content.pm.ApplicationInfo;
import android.os.Parcelable;
import android.util.ArrayMap;

import java.util.Set;

@@ -37,6 +38,15 @@ public interface ParsedProcess extends Parcelable {
    @NonNull
    String getName();

    /**
     * The app class names in this (potentially shared) process, from a package name to
     * the application class name.
     * It's a map, because in shared processes, different packages can have different application
     * classes.
     */
    @NonNull
    ArrayMap<String, String> getAppClassNamesByPackage();

    @ApplicationInfo.NativeHeapZeroInitialized
    int getNativeHeapZeroInitialized();
}
Loading