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

Commit f1e25135 authored by Ivan Chiang's avatar Ivan Chiang Committed by Android (Google) Code Review
Browse files

Merge changes from topic "package_info_apex_package_name" into main

* changes:
  [PM] Add new field mApexPackageName into PackageInfo
  [PM] Add APK-in-APEX info in ModuleInfo
parents cc7bb1af 57225ce2
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -12368,6 +12368,7 @@ package android.content.pm {
  public final class ModuleInfo implements android.os.Parcelable {
    method public int describeContents();
    method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @NonNull public java.util.Collection<java.lang.String> getApkInApexPackageNames();
    method @Nullable public CharSequence getName();
    method @Nullable public String getPackageName();
    method public boolean isHidden();
@@ -12378,6 +12379,7 @@ package android.content.pm {
  public class PackageInfo implements android.os.Parcelable {
    ctor public PackageInfo();
    method public int describeContents();
    method @FlaggedApi("android.content.pm.provide_info_of_apk_in_apex") @Nullable public String getApexPackageName();
    method @FlaggedApi("android.content.pm.archiving") public long getArchiveTimeMillis();
    method public long getLongVersionCode();
    method public void setLongVersionCode(long);
+39 −0
Original line number Diff line number Diff line
@@ -16,10 +16,15 @@

package android.content.pm;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
@@ -46,6 +51,13 @@ public final class ModuleInfo implements Parcelable {
    /** Whether or not this module is hidden from the user. */
    private boolean mHidden;

    /**
     * The list of the package names of all APK-in-APEX apps in the module, or
     * null if there are none.
     */
    @Nullable
    private List<String> mApkInApexPackageNames;

    // TODO: Decide whether we need an additional metadata bundle to support out of band
    // updates to ModuleInfo.
    //
@@ -61,6 +73,9 @@ public final class ModuleInfo implements Parcelable {
        mPackageName = orig.mPackageName;
        mHidden = orig.mHidden;
        mApexModuleName = orig.mApexModuleName;
        if (orig.mApkInApexPackageNames != null) {
            mApkInApexPackageNames = List.copyOf(orig.mApkInApexPackageNames);
        }
    }

    /** @hide Sets the public name of this module. */
@@ -107,6 +122,25 @@ public final class ModuleInfo implements Parcelable {
        return mApexModuleName;
    }

    /** @hide Sets the list of the package name of APK-in-APEX apps in this module. */
    public ModuleInfo setApkInApexPackageNames(@NonNull Collection<String> apkInApexPackageNames) {
        Objects.requireNonNull(apkInApexPackageNames);
        mApkInApexPackageNames = List.copyOf(apkInApexPackageNames);
        return this;
    }

    /**
     * Gets the list of the package name of all APK-in-APEX apps in the module.
     */
    @NonNull
    @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX)
    public Collection<String> getApkInApexPackageNames() {
        if (mApkInApexPackageNames == null) {
            return Collections.emptyList();
        }
        return mApkInApexPackageNames;
    }

    /** Returns a string representation of this object. */
    public String toString() {
        return "ModuleInfo{"
@@ -125,6 +159,7 @@ public final class ModuleInfo implements Parcelable {
        hashCode = 31 * hashCode + Objects.hashCode(mName);
        hashCode = 31 * hashCode + Objects.hashCode(mPackageName);
        hashCode = 31 * hashCode + Objects.hashCode(mApexModuleName);
        hashCode = 31 * hashCode + Objects.hashCode(mApkInApexPackageNames);
        hashCode = 31 * hashCode + Boolean.hashCode(mHidden);
        return hashCode;
    }
@@ -138,6 +173,7 @@ public final class ModuleInfo implements Parcelable {
        return Objects.equals(mName, other.mName)
                && Objects.equals(mPackageName, other.mPackageName)
                && Objects.equals(mApexModuleName, other.mApexModuleName)
                && Objects.equals(mApkInApexPackageNames, other.mApkInApexPackageNames)
                && mHidden == other.mHidden;
    }

@@ -147,6 +183,8 @@ public final class ModuleInfo implements Parcelable {
        dest.writeString(mPackageName);
        dest.writeBoolean(mHidden);
        dest.writeString(mApexModuleName);
        // Parcel#writeStringList handles null case, we can use it directly
        dest.writeStringList(mApkInApexPackageNames);
    }

    private ModuleInfo(Parcel source) {
@@ -154,6 +192,7 @@ public final class ModuleInfo implements Parcelable {
        mPackageName = source.readString();
        mHidden = source.readBoolean();
        mApexModuleName = source.readString();
        mApkInApexPackageNames = source.createStringArrayList();
    }

    public static final @android.annotation.NonNull Parcelable.Creator<ModuleInfo> CREATOR =
+40 −0
Original line number Diff line number Diff line
@@ -499,6 +499,16 @@ public class PackageInfo implements Parcelable {
     */
    public boolean isActiveApex;

    /**
     * If the package is an APEX package (i.e. the value of {@link #isApex}
     * is true), this field is the package name of the APEX. If the package
     * is one APK-in-APEX app, this field is the package name of the parent
     * APEX that contains the app. If the package is not one of the above
     * two cases, this field is {@code null}.
     */
    @Nullable
    private String mApexPackageName;

    public PackageInfo() {
    }

@@ -535,6 +545,26 @@ public class PackageInfo implements Parcelable {
        mArchiveTimeMillis = value;
    }

    /**
     * If the package is an APEX package (i.e. the value of {@link #isApex}
     * is true), returns the package name of the APEX. If the package
     * is one APK-in-APEX app, returns the package name of the parent
     * APEX that contains the app. If the package is not one of the above
     * two cases, returns {@code null}.
     */
    @Nullable
    @FlaggedApi(android.content.pm.Flags.FLAG_PROVIDE_INFO_OF_APK_IN_APEX)
    public String getApexPackageName() {
        return mApexPackageName;
    }

    /**
     * @hide
     */
    public void setApexPackageName(@Nullable String apexPackageName) {
        mApexPackageName = apexPackageName;
    }

    @Override
    public String toString() {
        return "PackageInfo{"
@@ -603,6 +633,12 @@ public class PackageInfo implements Parcelable {
        dest.writeBoolean(isApex);
        dest.writeBoolean(isActiveApex);
        dest.writeLong(mArchiveTimeMillis);
        if (mApexPackageName != null) {
            dest.writeInt(1);
            dest.writeString8(mApexPackageName);
        } else {
            dest.writeInt(0);
        }
        dest.restoreAllowSquashing(prevAllowSquashing);
    }

@@ -669,5 +705,9 @@ public class PackageInfo implements Parcelable {
        isApex = source.readBoolean();
        isActiveApex = source.readBoolean();
        mArchiveTimeMillis = source.readLong();
        int hasApexPackageName = source.readInt();
        if (hasApexPackageName != 0) {
            mApexPackageName = source.readString8();
        }
    }
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 static com.google.common.truth.Truth.assertThat;

import android.os.Parcel;
import android.platform.test.annotations.AppModeFull;
import android.text.TextUtils;

import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;

@RunWith(AndroidJUnit4.class)
@AppModeFull
public class ModuleInfoTest {

    private static final String APEX_MODULE_NAME = "apexModuleName";
    private static final String APK_IN_APEX_PACKAGE_NAME = "apkInApexPackageName";
    private static final String MODULE_PACKAGE_NAME = "modulePackageName";
    private static final String MODULE_NAME = "moduleName";

    @Test
    public void testSimple() {
        ModuleInfo info = new ModuleInfo();
        assertThat(info.toString()).isNotNull();
    }

    @Test
    public void testDefaultCopy() {
        ModuleInfo oldInfo = new ModuleInfo();
        ModuleInfo newInfo = new ModuleInfo(oldInfo);
        assertThat(newInfo).isEqualTo(oldInfo);
    }

    @Test
    public void testCopy() {
        boolean isHidden = false;
        ModuleInfo info = new ModuleInfo();
        info.setHidden(isHidden);
        info.setApexModuleName(APEX_MODULE_NAME);
        info.setPackageName(MODULE_PACKAGE_NAME);
        info.setName(MODULE_NAME);
        info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME));

        ModuleInfo newInfo = new ModuleInfo(info);
        assertThat(newInfo).isEqualTo(info);
    }

    @Test
    public void testGetApkInApexPackageNamesReturnEmptyListInDefault() {
        ModuleInfo info = new ModuleInfo();
        assertThat(info.getApkInApexPackageNames()).isNotNull();
        assertThat(info.getApkInApexPackageNames()).isEmpty();
    }

    @Test
    public void testModuleInfoParcelizeDeparcelize() {
        boolean isHidden = false;
        ModuleInfo info = new ModuleInfo();
        info.setHidden(isHidden);
        info.setApexModuleName(APEX_MODULE_NAME);
        info.setPackageName(MODULE_PACKAGE_NAME);
        info.setName(MODULE_NAME);
        info.setApkInApexPackageNames(List.of(APK_IN_APEX_PACKAGE_NAME));

        final Parcel p = Parcel.obtain();
        info.writeToParcel(p, 0);
        p.setDataPosition(0);

        final ModuleInfo targetInfo = ModuleInfo.CREATOR.createFromParcel(p);
        p.recycle();

        assertThat(info.isHidden()).isEqualTo(targetInfo.isHidden());
        assertThat(info.getApexModuleName()).isEqualTo(targetInfo.getApexModuleName());
        assertThat(info.getPackageName()).isEqualTo(targetInfo.getPackageName());
        assertThat(TextUtils.equals(info.getName(), targetInfo.getName())).isTrue();
        assertThat(info.getApkInApexPackageNames().toArray()).isEqualTo(
                targetInfo.getApkInApexPackageNames().toArray());
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.AuxiliaryResolveInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.Flags;
import android.content.pm.InstallSourceInfo;
import android.content.pm.InstantAppRequest;
import android.content.pm.InstantAppResolveInfo;
@@ -1511,6 +1512,13 @@ public class ComputerEngine implements Computer {
            packageInfo.packageName = packageInfo.applicationInfo.packageName =
                    resolveExternalPackageName(p);

            if (Flags.provideInfoOfApkInApex()) {
                final String apexModuleName =  ps.getApexModuleName();
                if (apexModuleName != null) {
                    packageInfo.setApexPackageName(
                            mApexManager.getActivePackageNameForApexModuleName(apexModuleName));
                }
            }
            return packageInfo;
        } else if ((flags & (MATCH_UNINSTALLED_PACKAGES | MATCH_ARCHIVED_PACKAGES)) != 0
                && PackageUserStateUtils.isAvailable(state, flags)) {
Loading