OSDN Git Service

Pass URLs to package verifiers
authorrich cannings <richc@google.com>
Mon, 20 Aug 2012 20:20:14 +0000 (13:20 -0700)
committerrich cannings <richc@google.com>
Mon, 20 Aug 2012 20:20:14 +0000 (13:20 -0700)
This change passes the originating URL and accompanied referrer to
package verifiers, when available.

Bug: 6544677
Change-Id: I9ebc71bc13f549bd88267e444816151a99bda000

api/current.txt
cmds/pm/src/com/android/commands/pm/Pm.java
core/java/android/app/ApplicationPackageManager.java
core/java/android/content/Intent.java
core/java/android/content/pm/IPackageManager.aidl
core/java/android/content/pm/PackageManager.java
core/java/android/content/pm/VerificationParams.aidl [new file with mode: 0644]
core/java/android/content/pm/VerificationParams.java [new file with mode: 0644]
core/tests/coretests/src/android/content/pm/VerificationParamsTest.java [new file with mode: 0644]
services/java/com/android/server/pm/PackageManagerService.java
test-runner/src/android/test/mock/MockPackageManager.java

index d6d1732..5e0b2e6 100644 (file)
@@ -5838,7 +5838,7 @@ package android.content {
     field public static final java.lang.String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
     field public static final java.lang.String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
     field public static final java.lang.String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
-    field public static final java.lang.String EXTRA_ORIGINATING_URL = "android.intent.extra.ORIGINATING_URL";
+    field public static final java.lang.String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
     field public static final java.lang.String EXTRA_PHONE_NUMBER = "android.intent.extra.PHONE_NUMBER";
     field public static final java.lang.String EXTRA_REFERRER = "android.intent.extra.REFERRER";
     field public static final java.lang.String EXTRA_REMOTE_INTENT_TOKEN = "android.intent.extra.remote_intent_token";
index eb1f9a2..b34fd05 100644 (file)
@@ -36,6 +36,7 @@ import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -787,6 +788,8 @@ public final class Pm {
         String macAlgo = null;
         byte[] macKey = null;
         byte[] tag = null;
+        String originatingUriString = null;
+        String referrer = null;
 
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
@@ -850,6 +853,20 @@ public final class Pm {
                     showUsage();
                     return;
                 }
+            } else if (opt.equals("--originating-uri")) {
+                originatingUriString = nextOptionData();
+                if (originatingUriString == null) {
+                    System.err.println("Error: must supply argument for --originating-uri");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--referrer")) {
+                referrer = nextOptionData();
+                if (referrer == null) {
+                    System.err.println("Error: must supply argument for --referrer");
+                    showUsage();
+                    return;
+                }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -897,6 +914,20 @@ public final class Pm {
 
         final Uri apkURI;
         final Uri verificationURI;
+        final Uri originatingURI;
+        final Uri referrerURI;
+
+        if (originatingUriString != null) {
+            originatingURI = Uri.parse(originatingUriString);
+        } else {
+            originatingURI = null;
+        }
+
+        if (referrer != null) {
+            referrerURI = Uri.parse(referrer);
+        } else {
+            referrerURI = null;
+        }
 
         // Populate apkURI, must be present
         final String apkFilePath = nextArg();
@@ -920,8 +951,11 @@ public final class Pm {
 
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
-            mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
-                    verificationURI, null, encryptionParams);
+            VerificationParams verificationParams = new VerificationParams(verificationURI,
+                    originatingURI, referrerURI, null);
+
+            mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+                    installerPackageName, verificationParams, encryptionParams);
 
             synchronized (obs) {
                 while (!obs.finished) {
@@ -1441,7 +1475,8 @@ public final class Pm {
         System.err.println("       pm list libraries");
         System.err.println("       pm path PACKAGE");
         System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
-        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
+        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]");
+        System.err.println("                  [--originating-uri <URI>] [--referrer <URI>] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm clear PACKAGE");
         System.err.println("       pm enable PACKAGE_OR_COMPONENT");
index e9c4701..7ab7086 100644 (file)
@@ -43,6 +43,7 @@ import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.ManifestDigest;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -984,6 +985,18 @@ final class ApplicationPackageManager extends PackageManager {
     }
 
     @Override
+         public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        try {
+            mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                    installerPackageName, verificationParams, encryptionParams);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
     public void verifyPendingInstall(int id, int response) {
         try {
             mPM.verifyPendingInstall(id, response);
index 0190555..06edf32 100644 (file)
@@ -571,7 +571,7 @@ import java.util.Set;
  *     <li> {@link #EXTRA_INITIAL_INTENTS}
  *     <li> {@link #EXTRA_INTENT}
  *     <li> {@link #EXTRA_KEY_EVENT}
- *     <li> {@link #EXTRA_ORIGINATING_URL}
+ *     <li> {@link #EXTRA_ORIGINATING_URI}
  *     <li> {@link #EXTRA_PHONE_NUMBER}
  *     <li> {@link #EXTRA_REFERRER}
  *     <li> {@link #EXTRA_REMOTE_INTENT_TOKEN}
@@ -1288,17 +1288,17 @@ public class Intent implements Parcelable, Cloneable {
             = "android.intent.extra.NOT_UNKNOWN_SOURCE";
 
     /**
-     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
-     * {@link #ACTION_VIEW} to indicate the URL from which the local APK in the Intent
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the URI from which the local APK in the Intent
      * data field originated from.
      */
-    public static final String EXTRA_ORIGINATING_URL
-            = "android.intent.extra.ORIGINATING_URL";
+    public static final String EXTRA_ORIGINATING_URI
+            = "android.intent.extra.ORIGINATING_URI";
 
     /**
-     * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} and
-     * {@link #ACTION_VIEW} to indicate the HTTP referrer associated with the Intent
-     * data field or {@link #EXTRA_ORIGINATING_URL}.
+     * Used as a URI extra field with {@link #ACTION_INSTALL_PACKAGE} and
+     * {@link #ACTION_VIEW} to indicate the HTTP referrer URI associated with the Intent
+     * data field or {@link #EXTRA_ORIGINATING_URI}.
      */
     public static final String EXTRA_REFERRER
             = "android.intent.extra.REFERRER";
index 6c19282..f266b00 100644 (file)
@@ -39,6 +39,7 @@ import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
@@ -362,6 +363,11 @@ interface IPackageManager {
             int flags, in String installerPackageName, in Uri verificationURI,
             in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
 
+    void installPackageWithVerificationAndEncryption(in Uri packageURI,
+            in IPackageInstallObserver observer, int flags, in String installerPackageName,
+            in VerificationParams verificationParams,
+            in ContainerEncryptionParams encryptionParams);
+
     void verifyPendingInstall(int id, int verificationCode);
 
     VerifierDeviceIdentity getVerifierDeviceIdentity();
index 2837931..e9e0ee3 100644 (file)
@@ -2227,6 +2227,37 @@ public abstract class PackageManager {
             ContainerEncryptionParams encryptionParams);
 
     /**
+     * Similar to
+     * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+     * with an extra verification information provided.
+     *
+     * @param packageURI The location of the package file to install. This can
+     *            be a 'file:' or a 'content:' URI.
+     * @param observer An observer callback to get notified when the package
+     *            installation is complete.
+     *            {@link IPackageInstallObserver#packageInstalled(String, int)}
+     *            will be called when that happens. observer may be null to
+     *            indicate that no callback is desired.
+     * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+     *            {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
+     *            .
+     * @param installerPackageName Optional package name of the application that
+     *            is performing the installation. This identifies which market
+     *            the package came from.
+     * @param verificationParams an object that holds signal information to
+     *            assist verification. May be {@code null}.
+     * @param encryptionParams if the package to be installed is encrypted,
+     *            these parameters describing the encryption and authentication
+     *            used. May be {@code null}.
+     *
+     * @hide
+     */
+    public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams,
+            ContainerEncryptionParams encryptionParams);
+
+    /**
      * Allows a package listening to the
      * {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
      * broadcast} to respond to the package manager. The response must include
diff --git a/core/java/android/content/pm/VerificationParams.aidl b/core/java/android/content/pm/VerificationParams.aidl
new file mode 100644 (file)
index 0000000..5bb7f69
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012, 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 VerificationParams;
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
new file mode 100644 (file)
index 0000000..9bec87e
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 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.content.pm.ManifestDigest;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents verification parameters used to verify packages to be installed.
+ *
+ * @hide
+ */
+public class VerificationParams implements Parcelable {
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "VerificationParams{";
+
+    /** The location of the supplementary verification file. */
+    private final Uri mVerificationURI;
+
+    /** URI referencing where the package was downloaded from. */
+    private final Uri mOriginatingURI;
+
+    /** HTTP referrer URI associated with the originatingURI. */
+    private final Uri mReferrer;
+
+    /**
+     * An object that holds the digest of the package which can be used to
+     * verify ownership.
+     */
+    private final ManifestDigest mManifestDigest;
+
+    /**
+     * Creates verification specifications for installing with application verification.
+     *
+     * @param verificationURI The location of the supplementary verification
+     *            file. This can be a 'file:' or a 'content:' URI. May be {@code null}.
+     * @param originatingURI URI referencing where the package was downloaded
+     *            from. May be {@code null}.
+     * @param referrer HTTP referrer URI associated with the originatingURI.
+     *            May be {@code null}.
+     * @param manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     */
+    public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
+            ManifestDigest manifestDigest) {
+        mVerificationURI = verificationURI;
+        mOriginatingURI = originatingURI;
+        mReferrer = referrer;
+        mManifestDigest = manifestDigest;
+    }
+
+    public Uri getVerificationURI() {
+        return mVerificationURI;
+    }
+
+    public Uri getOriginatingURI() {
+        return mOriginatingURI;
+    }
+
+    public Uri getReferrer() {
+        return mReferrer;
+    }
+
+    public ManifestDigest getManifestDigest() {
+        return mManifestDigest;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof VerificationParams)) {
+            return false;
+        }
+
+        final VerificationParams other = (VerificationParams) o;
+
+        if (mVerificationURI == null && other.mVerificationURI != null) {
+            return false;
+        }
+        if (!mVerificationURI.equals(other.mVerificationURI)) {
+            return false;
+        }
+
+        if (mOriginatingURI == null && other.mOriginatingURI != null) {
+            return false;
+        }
+        if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+            return false;
+        }
+
+        if (mReferrer == null && other.mReferrer != null) {
+            return false;
+        }
+        if (!mReferrer.equals(other.mReferrer)) {
+            return false;
+        }
+
+        if (mManifestDigest == null && other.mManifestDigest != null) {
+            return false;
+        }
+        if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+
+        hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
+        hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
+        hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
+        hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
+
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+        sb.append("mVerificationURI=");
+        sb.append(mVerificationURI.toString());
+        sb.append(",mOriginatingURI=");
+        sb.append(mOriginatingURI.toString());
+        sb.append(",mReferrer=");
+        sb.append(mReferrer.toString());
+        sb.append(",mManifestDigest=");
+        sb.append(mManifestDigest.toString());
+        sb.append('}');
+
+        return sb.toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mVerificationURI, 0);
+        dest.writeParcelable(mOriginatingURI, 0);
+        dest.writeParcelable(mReferrer, 0);
+        dest.writeParcelable(mManifestDigest, 0);
+    }
+
+
+    private VerificationParams(Parcel source) {
+        mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
+        mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
+        mReferrer = source.readParcelable(Uri.class.getClassLoader());
+        mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
+    }
+
+    public static final Parcelable.Creator<VerificationParams> CREATOR =
+            new Parcelable.Creator<VerificationParams>() {
+        public VerificationParams createFromParcel(Parcel source) {
+                return new VerificationParams(source);
+        }
+
+        public VerificationParams[] newArray(int size) {
+            return new VerificationParams[size];
+        }
+    };
+}
diff --git a/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java b/core/tests/coretests/src/android/content/pm/VerificationParamsTest.java
new file mode 100644 (file)
index 0000000..b814e2d
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 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.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+/**
+ * Tests the android.content.pm.VerificationParams class
+ *
+ * To test run:
+ * ./development/testrunner/runtest.py frameworks-core -c android.content.pm.VerificationParamsTest
+ */
+public class VerificationParamsTest extends AndroidTestCase {
+
+    private final static String VERIFICATION_URI_STRING = "http://verification.uri/path";
+    private final static String ORIGINATING_URI_STRING = "http://originating.uri/path";
+    private final static String REFERRER_STRING = "http://referrer.uri/path";
+    private final static byte[] DIGEST_BYTES = "fake digest".getBytes();
+
+    private final static Uri VERIFICATION_URI = Uri.parse(VERIFICATION_URI_STRING);
+    private final static Uri ORIGINATING_URI = Uri.parse(ORIGINATING_URI_STRING);
+    private final static Uri REFERRER = Uri.parse(REFERRER_STRING);
+
+    private final static ManifestDigest MANIFEST_DIGEST = new ManifestDigest(DIGEST_BYTES);
+
+    public void testParcel() throws Exception {
+        VerificationParams expected = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        VerificationParams actual = VerificationParams.CREATOR.createFromParcel(parcel);
+
+        assertEquals(VERIFICATION_URI, actual.getVerificationURI());
+
+        assertEquals(ORIGINATING_URI, actual.getOriginatingURI());
+
+        assertEquals(REFERRER, actual.getReferrer());
+
+        assertEquals(MANIFEST_DIGEST, actual.getManifestDigest());
+    }
+
+    public void testEquals_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+            REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse("http://a.different.uri/"), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse("http://a.different.uri/"), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testHashCode_Success() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_VerificationUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(null, Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_OriginatingUri_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse("http://a.different.uri/"),
+                Uri.parse(REFERRER_STRING), new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_Referrer_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING), null,
+                new ManifestDigest(DIGEST_BYTES));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_ManifestDigest_Failure() throws Exception {
+        VerificationParams params1 = new VerificationParams(VERIFICATION_URI, ORIGINATING_URI,
+                REFERRER, MANIFEST_DIGEST);
+
+        VerificationParams params2 = new VerificationParams(
+                Uri.parse(VERIFICATION_URI_STRING), Uri.parse(ORIGINATING_URI_STRING),
+                Uri.parse(REFERRER_STRING), new ManifestDigest("a different digest".getBytes()));
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
index 430edf7..be82b34 100644 (file)
@@ -79,6 +79,7 @@ import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
 import android.content.pm.ManifestDigest;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.net.Uri;
@@ -5351,7 +5352,17 @@ public class PackageManagerService extends IPackageManager.Stub {
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
             ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
+        VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+                manifestDigest);
+        installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+                installerPackageName, verificationParams, encryptionParams);
+    }
+
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
+                null);
 
         final int uid = Binder.getCallingUid();
 
@@ -5368,7 +5379,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
-                verificationURI, manifestDigest, encryptionParams);
+                verificationParams, encryptionParams);
         mHandler.sendMessage(msg);
     }
 
@@ -5798,8 +5809,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         private final Uri mPackageURI;
         final String installerPackageName;
-        final Uri verificationURI;
-        final ManifestDigest manifestDigest;
+        final VerificationParams verificationParams;
         private InstallArgs mArgs;
         private int mRet;
         private File mTempPackage;
@@ -5807,17 +5817,23 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, int flags,
-                String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
+                String installerPackageName, VerificationParams verificationParams,
                 ContainerEncryptionParams encryptionParams) {
             this.mPackageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
-            this.verificationURI = verificationURI;
-            this.manifestDigest = manifestDigest;
+            this.verificationParams = verificationParams;
             this.encryptionParams = encryptionParams;
         }
 
+        public ManifestDigest getManifestDigest() {
+            if (verificationParams == null) {
+                return null;
+            }
+            return verificationParams.getManifestDigest();
+        }
+
         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
             String packageName = pkgLite.packageName;
             int installLocation = pkgLite.installLocation;
@@ -6006,9 +6022,19 @@ public class PackageManagerService extends IPackageManager.Stub {
 
                     verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
 
-                    if (verificationURI != null) {
-                        verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
-                                verificationURI);
+                    if (verificationParams != null) {
+                        if (verificationParams.getVerificationURI() != null) {
+                           verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
+                                 verificationParams.getVerificationURI());
+                        }
+                        if (verificationParams.getOriginatingURI() != null) {
+                            verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
+                                  verificationParams.getOriginatingURI());
+                        }
+                        if (verificationParams.getReferrer() != null) {
+                            verification.putExtra(Intent.EXTRA_REFERRER,
+                                  verificationParams.getReferrer());
+                        }
                     }
 
                     final PackageVerificationState verificationState = new PackageVerificationState(
@@ -6344,7 +6370,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         FileInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest());
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
@@ -6631,7 +6657,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         AsecInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.flags,
-                    params.installerPackageName, params.manifestDigest);
+                    params.installerPackageName, params.getManifestDigest());
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
index ef14404..a85c8b5 100644 (file)
@@ -39,6 +39,7 @@ import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
+import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -519,6 +520,16 @@ public class MockPackageManager extends PackageManager {
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public void installPackageWithVerificationAndEncryption(Uri packageURI,
+            IPackageInstallObserver observer, int flags, String installerPackageName,
+            VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public void verifyPendingInstall(int id, int verificationCode) {
         throw new UnsupportedOperationException();