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

Commit c40b4f28 authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

Addressing API review comments.

Fixes: 169153620
Fixes: 168601298
Test: atest ChecksumsTest
Change-Id: Ibe593ccd388ad56f01ba0e3f58fb5a17c86e5e5c
parent 587ecc88
Loading
Loading
Loading
Loading
+12 −12
Original line number Original line Diff line number Diff line
@@ -11454,10 +11454,10 @@ package android.content.pm {
  public final class ApkChecksum implements android.os.Parcelable {
  public final class ApkChecksum implements android.os.Parcelable {
    method public int describeContents();
    method public int describeContents();
    method public int getKind();
    method @Nullable public java.security.cert.Certificate getInstallerCertificate() throws java.security.cert.CertificateException;
    method @Nullable public java.security.cert.Certificate getSourceCertificate() throws java.security.cert.CertificateException;
    method @Nullable public String getInstallerPackageName();
    method @Nullable public String getSourcePackageName();
    method @Nullable public String getSplitName();
    method @Nullable public String getSplitName();
    method public int getType();
    method @NonNull public byte[] getValue();
    method @NonNull public byte[] getValue();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ApkChecksum> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.ApkChecksum> CREATOR;
@@ -11567,17 +11567,17 @@ package android.content.pm {
  public final class Checksum implements android.os.Parcelable {
  public final class Checksum implements android.os.Parcelable {
    ctor public Checksum(int, @NonNull byte[]);
    ctor public Checksum(int, @NonNull byte[]);
    method public int describeContents();
    method public int describeContents();
    method public int getKind();
    method public int getType();
    method @NonNull public byte[] getValue();
    method @NonNull public byte[] getValue();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Checksum> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.Checksum> CREATOR;
    field public static final int PARTIAL_MERKLE_ROOT_1M_SHA256 = 32; // 0x20
    field public static final int TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256 = 32; // 0x20
    field public static final int PARTIAL_MERKLE_ROOT_1M_SHA512 = 64; // 0x40
    field public static final int TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512 = 64; // 0x40
    field @Deprecated public static final int WHOLE_MD5 = 2; // 0x2
    field @Deprecated public static final int TYPE_WHOLE_MD5 = 2; // 0x2
    field public static final int WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
    field public static final int TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 = 1; // 0x1
    field @Deprecated public static final int WHOLE_SHA1 = 4; // 0x4
    field @Deprecated public static final int TYPE_WHOLE_SHA1 = 4; // 0x4
    field public static final int WHOLE_SHA256 = 8; // 0x8
    field @Deprecated public static final int TYPE_WHOLE_SHA256 = 8; // 0x8
    field public static final int WHOLE_SHA512 = 16; // 0x10
    field @Deprecated public static final int TYPE_WHOLE_SHA512 = 16; // 0x10
  }
  }
  public class ComponentInfo extends android.content.pm.PackageItemInfo {
  public class ComponentInfo extends android.content.pm.PackageItemInfo {
@@ -12027,7 +12027,6 @@ package android.content.pm {
    method @Nullable public abstract android.graphics.drawable.Drawable getApplicationLogo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
    method @Nullable public abstract android.graphics.drawable.Drawable getApplicationLogo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
    method @NonNull public CharSequence getBackgroundPermissionOptionLabel();
    method @NonNull public CharSequence getBackgroundPermissionOptionLabel();
    method @Nullable public abstract android.content.pm.ChangedPackages getChangedPackages(@IntRange(from=0) int);
    method @Nullable public abstract android.content.pm.ChangedPackages getChangedPackages(@IntRange(from=0) int);
    method public void getChecksums(@NonNull String, boolean, int, @Nullable java.util.List<java.security.cert.Certificate>, @NonNull android.content.IntentSender) throws java.security.cert.CertificateEncodingException, java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
    method public abstract int getComponentEnabledSetting(@NonNull android.content.ComponentName);
    method public abstract int getComponentEnabledSetting(@NonNull android.content.ComponentName);
    method @NonNull public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
    method @NonNull public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
    method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo);
    method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo);
@@ -12100,6 +12099,7 @@ package android.content.pm {
    method @Deprecated public abstract void removePackageFromPreferred(@NonNull String);
    method @Deprecated public abstract void removePackageFromPreferred(@NonNull String);
    method public abstract void removePermission(@NonNull String);
    method public abstract void removePermission(@NonNull String);
    method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
    method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
    method public void requestChecksums(@NonNull String, boolean, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.IntentSender) throws java.security.cert.CertificateEncodingException, android.content.pm.PackageManager.NameNotFoundException;
    method @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
    method @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
    method @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
    method @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
    method @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
    method @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
+26 −16
Original line number Original line Diff line number Diff line
@@ -16,13 +16,13 @@


package android.app;
package android.app;


import static android.content.pm.Checksum.PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.Checksum.PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.Checksum.WHOLE_MD5;
import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
import static android.content.pm.Checksum.WHOLE_MERKLE_ROOT_4K_SHA256;
import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256;
import static android.content.pm.Checksum.WHOLE_SHA1;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA1;
import static android.content.pm.Checksum.WHOLE_SHA256;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
import static android.content.pm.Checksum.WHOLE_SHA512;
import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;


import android.annotation.DrawableRes;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -117,7 +117,6 @@ import dalvik.system.VMRuntime;


import libcore.util.EmptyArray;
import libcore.util.EmptyArray;


import java.io.IOException;
import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.security.cert.Certificate;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateEncodingException;
@@ -150,10 +149,11 @@ public class ApplicationPackageManager extends PackageManager {
    private static final int sDefaultFlags = GET_SHARED_LIBRARY_FILES;
    private static final int sDefaultFlags = GET_SHARED_LIBRARY_FILES;


    /** Default set of checksums - includes all available checksums.
    /** Default set of checksums - includes all available checksums.
     * @see PackageManager#getChecksums  */
     * @see PackageManager#requestChecksums  */
    private static final int DEFAULT_CHECKSUMS =
    private static final int DEFAULT_CHECKSUMS =
            WHOLE_MERKLE_ROOT_4K_SHA256 | WHOLE_MD5 | WHOLE_SHA1 | WHOLE_SHA256 | WHOLE_SHA512
            TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256
                    | PARTIAL_MERKLE_ROOT_1M_SHA256 | PARTIAL_MERKLE_ROOT_1M_SHA512;
                    | TYPE_WHOLE_SHA512 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256
                    | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;


    // Name of the resource which provides background permission button string
    // Name of the resource which provides background permission button string
    public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
    public static final String APP_PERMISSION_BUTTON_ALLOW_ALWAYS =
@@ -994,14 +994,24 @@ public class ApplicationPackageManager extends PackageManager {
    }
    }


    @Override
    @Override
    public void getChecksums(@NonNull String packageName, boolean includeSplits,
    public void requestChecksums(@NonNull String packageName, boolean includeSplits,
            @Checksum.Kind int required, @Nullable List<Certificate> trustedInstallers,
            @Checksum.Type int required, @NonNull List<Certificate> trustedInstallers,
            @NonNull IntentSender statusReceiver)
            @NonNull IntentSender statusReceiver)
            throws CertificateEncodingException, IOException, NameNotFoundException {
            throws CertificateEncodingException, NameNotFoundException {
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(packageName);
        Objects.requireNonNull(statusReceiver);
        Objects.requireNonNull(statusReceiver);
        Objects.requireNonNull(trustedInstallers);
        try {
        try {
            mPM.getChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
            if (trustedInstallers == TRUST_ALL) {
                trustedInstallers = null;
            } else if (trustedInstallers == TRUST_NONE) {
                trustedInstallers = Collections.emptyList();
            } else if (trustedInstallers.isEmpty()) {
                throw new IllegalArgumentException(
                        "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
                                + "list of certificates.");
            }
            mPM.requestChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
                    encodeCertificates(trustedInstallers), statusReceiver, getUserId());
                    encodeCertificates(trustedInstallers), statusReceiver, getUserId());
        } catch (ParcelableException e) {
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
+35 −37
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@ package android.content.pm;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.content.IntentSender;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;


@@ -31,12 +30,11 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.cert.X509Certificate;
import java.util.List;


/**
/**
 * A typed checksum of an APK.
 * A typed checksum of an APK.
 *
 *
 * @see PackageManager#getChecksums(String, boolean, int, List, IntentSender)
 * @see PackageManager#requestChecksums
 */
 */
@DataClass(genHiddenConstructor = true)
@DataClass(genHiddenConstructor = true)
@DataClass.Suppress({"getChecksum"})
@DataClass.Suppress({"getChecksum"})
@@ -52,20 +50,20 @@ public final class ApkChecksum implements Parcelable {
    /**
    /**
     * For Installer-provided checksums, package name of the Installer.
     * For Installer-provided checksums, package name of the Installer.
     */
     */
    private final @Nullable String mSourcePackageName;
    private final @Nullable String mInstallerPackageName;
    /**
    /**
     * For Installer-provided checksums, certificate of the Installer.
     * For Installer-provided checksums, certificate of the Installer.
     */
     */
    private final @Nullable byte[] mSourceCertificate;
    private final @Nullable byte[] mInstallerCertificate;


    /**
    /**
     * Constructor, internal use only.
     * Constructor, internal use only.
     *
     *
     * @hide
     * @hide
     */
     */
    public ApkChecksum(@Nullable String splitName, @Checksum.Kind int kind,
    public ApkChecksum(@Nullable String splitName, @Checksum.Type int type,
            @NonNull byte[] value) {
            @NonNull byte[] value) {
        this(splitName, new Checksum(kind, value), (String) null, (byte[]) null);
        this(splitName, new Checksum(type, value), (String) null, (byte[]) null);
    }
    }


    /**
    /**
@@ -73,19 +71,19 @@ public final class ApkChecksum implements Parcelable {
     *
     *
     * @hide
     * @hide
     */
     */
    public ApkChecksum(@Nullable String splitName, @Checksum.Kind int kind, @NonNull byte[] value,
    public ApkChecksum(@Nullable String splitName, @Checksum.Type int type, @NonNull byte[] value,
            @Nullable String sourcePackageName, @Nullable Certificate sourceCertificate)
            @Nullable String sourcePackageName, @Nullable Certificate sourceCertificate)
            throws CertificateEncodingException {
            throws CertificateEncodingException {
        this(splitName, new Checksum(kind, value), sourcePackageName,
        this(splitName, new Checksum(type, value), sourcePackageName,
                (sourceCertificate != null) ? sourceCertificate.getEncoded() : null);
                (sourceCertificate != null) ? sourceCertificate.getEncoded() : null);
    }
    }




    /**
    /**
     * Checksum kind.
     * Checksum type.
     */
     */
    public @Checksum.Kind int getKind() {
    public @Checksum.Type int getType() {
        return mChecksum.getKind();
        return mChecksum.getType();
    }
    }


    /**
    /**
@@ -96,24 +94,24 @@ public final class ApkChecksum implements Parcelable {
    }
    }


    /**
    /**
     * Returns raw bytes representing encoded certificate of the source of this checksum.
     * Returns raw bytes representing encoded certificate of the Installer.
     * @hide
     * @hide
     */
     */
    public @Nullable byte[] getSourceCertificateBytes() {
    public @Nullable byte[] getInstallerCertificateBytes() {
        return mSourceCertificate;
        return mInstallerCertificate;
    }
    }


    /**
    /**
     * Certificate of the source of this checksum.
     * For Installer-provided checksums, certificate of the Installer.
     * @throws CertificateException in case when certificate can't be re-created from serialized
     * @throws CertificateException in case when certificate can't be re-created from serialized
     * data.
     * data.
     */
     */
    public @Nullable Certificate getSourceCertificate() throws CertificateException {
    public @Nullable Certificate getInstallerCertificate() throws CertificateException {
        if (mSourceCertificate == null) {
        if (mInstallerCertificate == null) {
            return null;
            return null;
        }
        }
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final CertificateFactory cf = CertificateFactory.getInstance("X.509");
        final InputStream is = new ByteArrayInputStream(mSourceCertificate);
        final InputStream is = new ByteArrayInputStream(mInstallerCertificate);
        final X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
        final X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
        return cert;
        return cert;
    }
    }
@@ -140,9 +138,9 @@ public final class ApkChecksum implements Parcelable {
     *   Checksum for which split. Null indicates base.apk.
     *   Checksum for which split. Null indicates base.apk.
     * @param checksum
     * @param checksum
     *   Checksum.
     *   Checksum.
     * @param sourcePackageName
     * @param installerPackageName
     *   For Installer-provided checksums, package name of the Installer.
     *   For Installer-provided checksums, package name of the Installer.
     * @param sourceCertificate
     * @param installerCertificate
     *   For Installer-provided checksums, certificate of the Installer.
     *   For Installer-provided checksums, certificate of the Installer.
     * @hide
     * @hide
     */
     */
@@ -150,14 +148,14 @@ public final class ApkChecksum implements Parcelable {
    public ApkChecksum(
    public ApkChecksum(
            @Nullable String splitName,
            @Nullable String splitName,
            @NonNull Checksum checksum,
            @NonNull Checksum checksum,
            @Nullable String sourcePackageName,
            @Nullable String installerPackageName,
            @Nullable byte[] sourceCertificate) {
            @Nullable byte[] installerCertificate) {
        this.mSplitName = splitName;
        this.mSplitName = splitName;
        this.mChecksum = checksum;
        this.mChecksum = checksum;
        com.android.internal.util.AnnotationValidations.validate(
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mChecksum);
                NonNull.class, null, mChecksum);
        this.mSourcePackageName = sourcePackageName;
        this.mInstallerPackageName = installerPackageName;
        this.mSourceCertificate = sourceCertificate;
        this.mInstallerCertificate = installerCertificate;


        // onConstructed(); // You can define this method to get a callback
        // onConstructed(); // You can define this method to get a callback
    }
    }
@@ -174,8 +172,8 @@ public final class ApkChecksum implements Parcelable {
     * For Installer-provided checksums, package name of the Installer.
     * For Installer-provided checksums, package name of the Installer.
     */
     */
    @DataClass.Generated.Member
    @DataClass.Generated.Member
    public @Nullable String getSourcePackageName() {
    public @Nullable String getInstallerPackageName() {
        return mSourcePackageName;
        return mInstallerPackageName;
    }
    }


    @Override
    @Override
@@ -186,13 +184,13 @@ public final class ApkChecksum implements Parcelable {


        byte flg = 0;
        byte flg = 0;
        if (mSplitName != null) flg |= 0x1;
        if (mSplitName != null) flg |= 0x1;
        if (mSourcePackageName != null) flg |= 0x4;
        if (mInstallerPackageName != null) flg |= 0x4;
        if (mSourceCertificate != null) flg |= 0x8;
        if (mInstallerCertificate != null) flg |= 0x8;
        dest.writeByte(flg);
        dest.writeByte(flg);
        if (mSplitName != null) dest.writeString(mSplitName);
        if (mSplitName != null) dest.writeString(mSplitName);
        dest.writeTypedObject(mChecksum, flags);
        dest.writeTypedObject(mChecksum, flags);
        if (mSourcePackageName != null) dest.writeString(mSourcePackageName);
        if (mInstallerPackageName != null) dest.writeString(mInstallerPackageName);
        if (mSourceCertificate != null) dest.writeByteArray(mSourceCertificate);
        if (mInstallerCertificate != null) dest.writeByteArray(mInstallerCertificate);
    }
    }


    @Override
    @Override
@@ -209,15 +207,15 @@ public final class ApkChecksum implements Parcelable {
        byte flg = in.readByte();
        byte flg = in.readByte();
        String splitName = (flg & 0x1) == 0 ? null : in.readString();
        String splitName = (flg & 0x1) == 0 ? null : in.readString();
        Checksum checksum = (Checksum) in.readTypedObject(Checksum.CREATOR);
        Checksum checksum = (Checksum) in.readTypedObject(Checksum.CREATOR);
        String sourcePackageName = (flg & 0x4) == 0 ? null : in.readString();
        String installerPackageName = (flg & 0x4) == 0 ? null : in.readString();
        byte[] sourceCertificate = (flg & 0x8) == 0 ? null : in.createByteArray();
        byte[] installerCertificate = (flg & 0x8) == 0 ? null : in.createByteArray();


        this.mSplitName = splitName;
        this.mSplitName = splitName;
        this.mChecksum = checksum;
        this.mChecksum = checksum;
        com.android.internal.util.AnnotationValidations.validate(
        com.android.internal.util.AnnotationValidations.validate(
                NonNull.class, null, mChecksum);
                NonNull.class, null, mChecksum);
        this.mSourcePackageName = sourcePackageName;
        this.mInstallerPackageName = installerPackageName;
        this.mSourceCertificate = sourceCertificate;
        this.mInstallerCertificate = installerCertificate;


        // onConstructed(); // You can define this method to get a callback
        // onConstructed(); // You can define this method to get a callback
    }
    }
@@ -237,10 +235,10 @@ public final class ApkChecksum implements Parcelable {
    };
    };


    @DataClass.Generated(
    @DataClass.Generated(
            time = 1600407436287L,
            time = 1601589269293L,
            codegenVersion = "1.0.15",
            codegenVersion = "1.0.15",
            sourceFile = "frameworks/base/core/java/android/content/pm/ApkChecksum.java",
            sourceFile = "frameworks/base/core/java/android/content/pm/ApkChecksum.java",
            inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mSourcePackageName\nprivate final @android.annotation.Nullable byte[] mSourceCertificate\npublic @android.content.pm.Checksum.Kind int getKind()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getSourceCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getSourceCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
            inputSignatures = "private final @android.annotation.Nullable java.lang.String mSplitName\nprivate final @android.annotation.NonNull android.content.pm.Checksum mChecksum\nprivate final @android.annotation.Nullable java.lang.String mInstallerPackageName\nprivate final @android.annotation.Nullable byte[] mInstallerCertificate\npublic @android.content.pm.Checksum.Type int getType()\npublic @android.annotation.NonNull byte[] getValue()\npublic @android.annotation.Nullable byte[] getInstallerCertificateBytes()\npublic @android.annotation.Nullable java.security.cert.Certificate getInstallerCertificate()\nclass ApkChecksum extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genHiddenConstructor=true)")
    @Deprecated
    @Deprecated
    private void __metadata() {}
    private void __metadata() {}


+53 −53

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Original line Diff line number Diff line
@@ -749,7 +749,7 @@ interface IPackageManager {


    void notifyPackagesReplacedReceived(in String[] packages);
    void notifyPackagesReplacedReceived(in String[] packages);


    void getChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IntentSender statusReceiver, int userId);
    void requestChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IntentSender statusReceiver, int userId);


    //------------------------------------------------------------------------
    //------------------------------------------------------------------------
    //
    //
Loading