Merge "Infrastructure to support package verifier"
This commit is contained in:
@@ -772,18 +772,33 @@ public final class Pm {
|
||||
}
|
||||
}
|
||||
|
||||
String apkFilePath = nextArg();
|
||||
final Uri apkURI;
|
||||
final Uri verificationURI;
|
||||
|
||||
// Populate apkURI, must be present
|
||||
final String apkFilePath = nextArg();
|
||||
System.err.println("\tpkg: " + apkFilePath);
|
||||
if (apkFilePath == null) {
|
||||
if (apkFilePath != null) {
|
||||
apkURI = Uri.fromFile(new File(apkFilePath));
|
||||
} else {
|
||||
System.err.println("Error: no package specified");
|
||||
showUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate verificationURI, optionally present
|
||||
final String verificationFilePath = nextArg();
|
||||
if (verificationFilePath != null) {
|
||||
System.err.println("\tver: " + verificationFilePath);
|
||||
verificationURI = Uri.fromFile(new File(verificationFilePath));
|
||||
} else {
|
||||
verificationURI = null;
|
||||
}
|
||||
|
||||
PackageInstallObserver obs = new PackageInstallObserver();
|
||||
try {
|
||||
mPm.installPackage(Uri.fromFile(new File(apkFilePath)), obs, installFlags,
|
||||
installerPackageName);
|
||||
mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
|
||||
verificationURI, null);
|
||||
|
||||
synchronized (obs) {
|
||||
while (!obs.finished) {
|
||||
|
||||
@@ -41,11 +41,11 @@ import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.ManifestDigest;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
@@ -940,6 +940,27 @@ final class ApplicationPackageManager extends PackageManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
|
||||
int flags, String installerPackageName, Uri verificationURI,
|
||||
ManifestDigest manifestDigest) {
|
||||
try {
|
||||
mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName,
|
||||
verificationURI, manifestDigest);
|
||||
} catch (RemoteException e) {
|
||||
// Should never happen!
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyPendingInstall(int id, boolean verified, String failureMessage) {
|
||||
try {
|
||||
mPM.verifyPendingInstall(id, verified, failureMessage);
|
||||
} catch (RemoteException e) {
|
||||
// Should never happen!
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInstallerPackageName(String targetPackage,
|
||||
String installerPackageName) {
|
||||
|
||||
@@ -1529,6 +1529,18 @@ public class Intent implements Parcelable, Cloneable {
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH";
|
||||
|
||||
/**
|
||||
* Broadcast Action: Sent to the system package verifier when a package
|
||||
* needs to be verified. The data contains the package URI.
|
||||
* <p class="note">
|
||||
* This is a protected intent that can only be sent by the system.
|
||||
* </p>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
|
||||
public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION";
|
||||
|
||||
/**
|
||||
* Broadcast Action: Resources for a set of packages (which were
|
||||
* previously unavailable) are currently
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.pm.IPackageStatsObserver;
|
||||
import android.content.pm.InstrumentationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ManifestDigest;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.PermissionGroupInfo;
|
||||
@@ -346,4 +347,10 @@ interface IPackageManager {
|
||||
|
||||
UserInfo createUser(in String name, int flags);
|
||||
boolean removeUser(int userId);
|
||||
|
||||
void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer,
|
||||
int flags, in String installerPackageName, in Uri verificationURI,
|
||||
in ManifestDigest manifestDigest);
|
||||
|
||||
void verifyPendingInstall(int id, boolean verified, in String message);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ManifestDigest;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -289,11 +290,19 @@ public abstract class PackageManager {
|
||||
public static final int INSTALL_EXTERNAL = 0x00000008;
|
||||
|
||||
/**
|
||||
* Flag parameter for {@link #installPackage} to indicate that this
|
||||
* package has to be installed on the sdcard.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_INTERNAL = 0x00000010;
|
||||
* Flag parameter for {@link #installPackage} to indicate that this package
|
||||
* has to be installed on the sdcard.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_INTERNAL = 0x00000010;
|
||||
|
||||
/**
|
||||
* Flag parameter for {@link #installPackage} to indicate that this install
|
||||
* was initiated via ADB.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_FROM_ADB = 0x00000020;
|
||||
|
||||
/**
|
||||
* Flag parameter for
|
||||
@@ -482,6 +491,30 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
|
||||
|
||||
/**
|
||||
* Installation return code: this is passed to the {@link IPackageInstallObserver} by
|
||||
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
|
||||
* the new package couldn't be installed because the verification timed out.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;
|
||||
|
||||
/**
|
||||
* Installation return code: this is passed to the {@link IPackageInstallObserver} by
|
||||
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
|
||||
* the new package couldn't be installed because the verification did not succeed.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;
|
||||
|
||||
/**
|
||||
* Installation return code: this is passed to the {@link IPackageInstallObserver} by
|
||||
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
|
||||
* the package changed from what the calling program expected.
|
||||
* @hide
|
||||
*/
|
||||
public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;
|
||||
|
||||
/**
|
||||
* Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
|
||||
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
|
||||
@@ -994,36 +1027,64 @@ public abstract class PackageManager {
|
||||
public static final String ACTION_CLEAN_EXTERNAL_STORAGE
|
||||
= "android.content.pm.CLEAN_EXTERNAL_STORAGE";
|
||||
|
||||
/**
|
||||
* Extra field name for the URI to a verification file. Passed to a package
|
||||
* verifier.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_VERIFICATION_URI = "android.content.pm.extra.VERIFICATION_URI";
|
||||
|
||||
/**
|
||||
* Extra field name for the ID of a package pending verification. Passed to
|
||||
* a package verifier and is used to call back to
|
||||
* {@link PackageManager#verifyPendingInstall(int, boolean)}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_VERIFICATION_ID = "android.content.pm.extra.VERIFICATION_ID";
|
||||
|
||||
/**
|
||||
* Extra field name for the package identifier which is trying to install
|
||||
* the package.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_VERIFICATION_INSTALLER_PACKAGE
|
||||
= "android.content.pm.extra.VERIFICATION_INSTALLER_PACKAGE";
|
||||
|
||||
/**
|
||||
* Extra field name for the requested install flags for a package pending
|
||||
* verification. Passed to a package verifier.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRA_VERIFICATION_INSTALL_FLAGS
|
||||
= "android.content.pm.extra.VERIFICATION_INSTALL_FLAGS";
|
||||
|
||||
/**
|
||||
* Retrieve overall information about an application package that is
|
||||
* installed on the system.
|
||||
*
|
||||
* <p>Throws {@link NameNotFoundException} if a package with the given
|
||||
* name can not be found on the system.
|
||||
* <p>
|
||||
* Throws {@link NameNotFoundException} if a package with the given name can
|
||||
* not be found on the system.
|
||||
*
|
||||
* @param packageName The full name (i.e. com.google.apps.contacts) of the
|
||||
* desired package.
|
||||
|
||||
* desired package.
|
||||
* @param flags Additional option flags. Use any combination of
|
||||
* {@link #GET_ACTIVITIES},
|
||||
* {@link #GET_GIDS},
|
||||
* {@link #GET_CONFIGURATIONS},
|
||||
* {@link #GET_INSTRUMENTATION},
|
||||
* {@link #GET_PERMISSIONS},
|
||||
* {@link #GET_PROVIDERS},
|
||||
* {@link #GET_RECEIVERS},
|
||||
* {@link #GET_SERVICES},
|
||||
* {@link #GET_SIGNATURES},
|
||||
* {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
|
||||
*
|
||||
* @return Returns a PackageInfo object containing information about the package.
|
||||
* If flag GET_UNINSTALLED_PACKAGES is set and if the package is not
|
||||
* found in the list of installed applications, the package information is
|
||||
* retrieved from the list of uninstalled applications(which includes
|
||||
* installed applications as well as applications
|
||||
* with data directory ie applications which had been
|
||||
* {@link #GET_ACTIVITIES}, {@link #GET_GIDS},
|
||||
* {@link #GET_CONFIGURATIONS}, {@link #GET_INSTRUMENTATION},
|
||||
* {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
|
||||
* {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
|
||||
* {@link #GET_SIGNATURES}, {@link #GET_UNINSTALLED_PACKAGES} to
|
||||
* modify the data returned.
|
||||
* @return Returns a PackageInfo object containing information about the
|
||||
* package. If flag GET_UNINSTALLED_PACKAGES is set and if the
|
||||
* package is not found in the list of installed applications, the
|
||||
* package information is retrieved from the list of uninstalled
|
||||
* applications(which includes installed applications as well as
|
||||
* applications with data directory ie applications which had been
|
||||
* deleted with DONT_DELTE_DATA flag set).
|
||||
*
|
||||
* @see #GET_ACTIVITIES
|
||||
* @see #GET_GIDS
|
||||
* @see #GET_CONFIGURATIONS
|
||||
@@ -1034,7 +1095,6 @@ public abstract class PackageManager {
|
||||
* @see #GET_SERVICES
|
||||
* @see #GET_SIGNATURES
|
||||
* @see #GET_UNINSTALLED_PACKAGES
|
||||
*
|
||||
*/
|
||||
public abstract PackageInfo getPackageInfo(String packageName, int flags)
|
||||
throws NameNotFoundException;
|
||||
@@ -2060,6 +2120,46 @@ public abstract class PackageManager {
|
||||
Uri packageURI, IPackageInstallObserver observer, int flags,
|
||||
String installerPackageName);
|
||||
|
||||
/**
|
||||
* Similar to
|
||||
* {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
|
||||
* with an extra verification file 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 verificationURI The location of the supplementary verification
|
||||
* file. This can be a 'file:' or a 'content:' URI.
|
||||
* @hide
|
||||
*/
|
||||
public abstract void installPackageWithVerification(Uri packageURI,
|
||||
IPackageInstallObserver observer, int flags, String installerPackageName,
|
||||
Uri verificationURI, ManifestDigest manifestDigest);
|
||||
|
||||
/**
|
||||
* Allows a package listening to the
|
||||
* {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION package verification
|
||||
* broadcast} to respond to the package manager.
|
||||
*
|
||||
* @param id pending package identifier as passed via the
|
||||
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra
|
||||
* @param verified whether the package was verified as valid
|
||||
* @param failureMessage if verification was false, this is the error
|
||||
* message that may be shown to the user
|
||||
* @hide
|
||||
*/
|
||||
public abstract void verifyPendingInstall(int id, boolean verified, String failureMessage);
|
||||
|
||||
/**
|
||||
* Change the installer associated with a given package. There are limitations
|
||||
* on how the installer package can be changed; in particular:
|
||||
|
||||
@@ -3960,6 +3960,12 @@ public final class Settings {
|
||||
public static final String WEB_AUTOFILL_QUERY_URL =
|
||||
"web_autofill_query_url";
|
||||
|
||||
/** Whether package verification is enabled. {@hide} */
|
||||
public static final String PACKAGE_VERIFIER_ENABLE = "verifier_enable";
|
||||
|
||||
/** Timeout for package verification. {@hide} */
|
||||
public static final String PACKAGE_VERIFIER_TIMEOUT = "verifier_timeout";
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
<protected-broadcast android:name="android.intent.action.PACKAGE_RESTARTED" />
|
||||
<protected-broadcast android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
|
||||
<protected-broadcast android:name="android.intent.action.PACKAGE_FIRST_LAUNCH" />
|
||||
<protected-broadcast android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION" />
|
||||
<protected-broadcast android:name="android.intent.action.UID_REMOVED" />
|
||||
<protected-broadcast android:name="android.intent.action.CONFIGURATION_CHANGED" />
|
||||
<protected-broadcast android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
@@ -1429,6 +1430,24 @@
|
||||
android:protectionLevel="signature" />
|
||||
<uses-permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"/>
|
||||
|
||||
<!-- Package verifier needs to have this permission before the PackageManager will
|
||||
trust it to verify packages.
|
||||
@hide
|
||||
-->
|
||||
<permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT"
|
||||
android:label="@string/permlab_packageVerificationAgent"
|
||||
android:description="@string/permdesc_packageVerificationAgent"
|
||||
android:protectionLevel="signatureOrSystem" />
|
||||
|
||||
<!-- Must be required by package verifier receiver, to ensure that only the
|
||||
system can interact with it.
|
||||
@hide
|
||||
-->
|
||||
<permission android:name="android.permission.BIND_PACKAGE_VERIFIER"
|
||||
android:label="@string/permlab_bindPackageVerifier"
|
||||
android:description="@string/permdesc_bindPackageVerifier"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- The system process is explicitly the only one allowed to launch the
|
||||
confirmation UI for full backup/restore -->
|
||||
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
|
||||
|
||||
@@ -2181,6 +2181,22 @@
|
||||
Browser\'s geolocation permissions. Malicious applications
|
||||
can use this to allow sending location information to arbitrary web sites.</string>
|
||||
|
||||
<!-- Title of an application permission which allows the application to verify whether
|
||||
a different package is able to be installed by some internal logic. [CHAR LIMIT=40] -->
|
||||
<string name="permlab_packageVerificationAgent">verify packages</string>
|
||||
<!-- Description of an application permission which allows the application to verify whether
|
||||
a different package is able to be installed by some internal heuristic. [CHAR LIMIT=NONE] -->
|
||||
<string name="permdesc_packageVerificationAgent">Allows the application to verify a package is
|
||||
installable.</string>
|
||||
|
||||
<!-- Title of an application permission which allows the application to verify whether
|
||||
a different package is able to be installed by some internal heuristic. [CHAR LIMIT=40] -->
|
||||
<string name="permlab_bindPackageVerifier">bind to a package verifier</string>
|
||||
<!-- Description of an application permission which allows the application to verify whether
|
||||
a different package is able to be installed by some internal heuristic. [CHAR LIMIT=NONE] -->
|
||||
<string name="permdesc_bindPackageVerifier">Allows the holder to make requests of
|
||||
package verifiers. Should never be needed for normal applications.</string>
|
||||
|
||||
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Text in the save password dialog, asking if the browser should remember a password. -->
|
||||
<string name="save_password_message">Do you want the browser to remember this password?</string>
|
||||
<!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Button in the save password dialog, saying not to remember this password. -->
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.app.ActivityManagerNative;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.admin.IDevicePolicyManager;
|
||||
import android.app.backup.IBackupManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
@@ -69,6 +70,7 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.ManifestDigest;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -188,6 +190,17 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
|
||||
static final int REMOVE_CHATTY = 1<<16;
|
||||
|
||||
/**
|
||||
* Whether verification is enabled by default.
|
||||
*/
|
||||
private static final boolean DEFAULT_VERIFY_ENABLE = true;
|
||||
|
||||
/**
|
||||
* The default maximum time to wait for the verification agent to return in
|
||||
* milliseconds.
|
||||
*/
|
||||
private static final long DEFAULT_VERIFICATION_TIMEOUT = 60 * 1000;
|
||||
|
||||
static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
|
||||
|
||||
static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
|
||||
@@ -333,6 +346,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// Broadcast actions that are only available to the system.
|
||||
final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
|
||||
|
||||
/** List of packages waiting for verification. */
|
||||
final SparseArray<InstallArgs> mPendingVerification = new SparseArray<InstallArgs>();
|
||||
|
||||
/** Token for keys in mPendingVerification. */
|
||||
private int mPendingVerificationToken = 0;
|
||||
|
||||
boolean mSystemReady;
|
||||
boolean mSafeMode;
|
||||
boolean mHasSystemUidErrors;
|
||||
@@ -364,6 +383,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
static final int UPDATED_MEDIA_STATUS = 12;
|
||||
static final int WRITE_SETTINGS = 13;
|
||||
static final int WRITE_STOPPED_PACKAGES = 14;
|
||||
static final int PACKAGE_VERIFIED = 15;
|
||||
static final int CHECK_PENDING_VERIFICATION = 16;
|
||||
|
||||
static final int WRITE_SETTINGS_DELAY = 10*1000; // 10 seconds
|
||||
|
||||
@@ -444,10 +465,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
void doHandleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case INIT_COPY: {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "init_copy");
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "init_copy");
|
||||
HandlerParams params = (HandlerParams) msg.obj;
|
||||
int idx = mPendingInstalls.size();
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "idx=" + idx);
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "idx=" + idx);
|
||||
// If a bind was already initiated we dont really
|
||||
// need to do anything. The pending install
|
||||
// will be processed later on.
|
||||
@@ -474,7 +495,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
break;
|
||||
}
|
||||
case MCS_BOUND: {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_bound");
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_bound");
|
||||
if (msg.obj != null) {
|
||||
mContainerService = (IMediaContainerService) msg.obj;
|
||||
}
|
||||
@@ -525,8 +546,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MCS_RECONNECT : {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_reconnect");
|
||||
case MCS_RECONNECT: {
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_reconnect");
|
||||
if (mPendingInstalls.size() > 0) {
|
||||
if (mBound) {
|
||||
disconnectService();
|
||||
@@ -543,27 +564,31 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MCS_UNBIND : {
|
||||
case MCS_UNBIND: {
|
||||
// If there is no actual work left, then time to unbind.
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_unbind");
|
||||
if (mPendingInstalls.size() == 0) {
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_unbind");
|
||||
|
||||
if (mPendingInstalls.size() == 0 && mPendingVerification.size() == 0) {
|
||||
if (mBound) {
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "calling disconnectService()");
|
||||
|
||||
disconnectService();
|
||||
}
|
||||
} else {
|
||||
} else if (mPendingInstalls.size() > 0) {
|
||||
// There are more pending requests in queue.
|
||||
// Just post MCS_BOUND message to trigger processing
|
||||
// of next pending install.
|
||||
mHandler.sendEmptyMessage(MCS_BOUND);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MCS_GIVE_UP: {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "mcs_giveup too many retries");
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "mcs_giveup too many retries");
|
||||
mPendingInstalls.remove(0);
|
||||
break;
|
||||
}
|
||||
case SEND_PENDING_BROADCAST : {
|
||||
case SEND_PENDING_BROADCAST: {
|
||||
String packages[];
|
||||
ArrayList<String> components[];
|
||||
int size = 0;
|
||||
@@ -707,6 +732,52 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
||||
} break;
|
||||
case CHECK_PENDING_VERIFICATION: {
|
||||
final int verificationId = msg.arg1;
|
||||
final InstallArgs args = mPendingVerification.get(verificationId);
|
||||
|
||||
if (args != null) {
|
||||
Slog.i(TAG, "Validation timed out for " + args.packageURI.toString());
|
||||
mPendingVerification.remove(verificationId);
|
||||
|
||||
int ret = PackageManager.INSTALL_FAILED_VERIFICATION_TIMEOUT;
|
||||
processPendingInstall(args, ret);
|
||||
|
||||
mHandler.sendEmptyMessage(MCS_UNBIND);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PACKAGE_VERIFIED: {
|
||||
final int verificationId = msg.arg1;
|
||||
final boolean verified = msg.arg2 == 1 ? true : false;
|
||||
|
||||
final InstallArgs args = mPendingVerification.get(verificationId);
|
||||
if (args == null) {
|
||||
Slog.w(TAG, "Invalid validation token " + verificationId + " received");
|
||||
break;
|
||||
}
|
||||
|
||||
mPendingVerification.remove(verificationId);
|
||||
|
||||
int ret;
|
||||
if (verified) {
|
||||
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||
try {
|
||||
ret = args.copyApk(mContainerService, true);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Could not contact the ContainerService");
|
||||
}
|
||||
} else {
|
||||
ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
|
||||
}
|
||||
|
||||
processPendingInstall(args, ret);
|
||||
|
||||
mHandler.sendEmptyMessage(MCS_UNBIND);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4693,12 +4764,45 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
public void installPackage(
|
||||
final Uri packageURI, final IPackageInstallObserver observer, final int flags,
|
||||
final String installerPackageName) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.INSTALL_PACKAGES, null);
|
||||
installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
|
||||
null);
|
||||
}
|
||||
|
||||
Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||
msg.obj = new InstallParams(packageURI, observer, flags,
|
||||
installerPackageName);
|
||||
@Override
|
||||
public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
|
||||
int flags, String installerPackageName, Uri verificationURI,
|
||||
ManifestDigest manifestDigest) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
|
||||
|
||||
final int uid = Binder.getCallingUid();
|
||||
|
||||
final int filteredFlags;
|
||||
|
||||
if (uid == Process.SHELL_UID || uid == 0) {
|
||||
if (DEBUG_INSTALL) {
|
||||
Slog.v(TAG, "Install from ADB");
|
||||
}
|
||||
filteredFlags = flags | PackageManager.INSTALL_FROM_ADB;
|
||||
} else {
|
||||
filteredFlags = flags & ~PackageManager.INSTALL_FROM_ADB;
|
||||
}
|
||||
|
||||
final Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||
msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
|
||||
verificationURI, manifestDigest);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyPendingInstall(int id, boolean verified, String message)
|
||||
throws RemoteException {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, null);
|
||||
|
||||
final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
|
||||
msg.arg1 = id;
|
||||
msg.arg2 = verified ? 1 : 0;
|
||||
msg.obj = message;
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
@@ -4713,6 +4817,28 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the verification agent timeout.
|
||||
*
|
||||
* @return verification timeout in milliseconds
|
||||
*/
|
||||
private long getVerificationTimeout() {
|
||||
return android.provider.Settings.Secure.getLong(mContext.getContentResolver(),
|
||||
android.provider.Settings.Secure.PACKAGE_VERIFIER_TIMEOUT,
|
||||
DEFAULT_VERIFICATION_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not package verification has been enabled.
|
||||
*
|
||||
* @return true if verification should be performed
|
||||
*/
|
||||
private boolean isVerificationEnabled() {
|
||||
return android.provider.Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
android.provider.Settings.Secure.PACKAGE_VERIFIER_ENABLE,
|
||||
DEFAULT_VERIFY_ENABLE ? 1 : 0) == 1 ? true : false;
|
||||
}
|
||||
|
||||
public void setInstallerPackageName(String targetPackage, String installerPackageName) {
|
||||
final int uid = Binder.getCallingUid();
|
||||
// writer
|
||||
@@ -4856,15 +4982,21 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
});
|
||||
}
|
||||
|
||||
abstract class HandlerParams {
|
||||
final static int MAX_RETRIES = 4;
|
||||
int retry = 0;
|
||||
private abstract class HandlerParams {
|
||||
private static final int MAX_RETRIES = 4;
|
||||
|
||||
/**
|
||||
* Number of times startCopy() has been attempted and had a non-fatal
|
||||
* error.
|
||||
*/
|
||||
private int mRetries = 0;
|
||||
|
||||
final boolean startCopy() {
|
||||
boolean res;
|
||||
try {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "startCopy");
|
||||
retry++;
|
||||
if (retry > MAX_RETRIES) {
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy");
|
||||
|
||||
if (++mRetries > MAX_RETRIES) {
|
||||
Slog.w(TAG, "Failed to invoke remote methods on default container service. Giving up");
|
||||
mHandler.sendEmptyMessage(MCS_GIVE_UP);
|
||||
handleServiceError();
|
||||
@@ -4874,7 +5006,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
res = true;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "Posting install MCS_RECONNECT");
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "Posting install MCS_RECONNECT");
|
||||
mHandler.sendEmptyMessage(MCS_RECONNECT);
|
||||
res = false;
|
||||
}
|
||||
@@ -4883,10 +5015,11 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
final void serviceError() {
|
||||
if (DEBUG_SD_INSTALL) Log.i(TAG, "serviceError");
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "serviceError");
|
||||
handleServiceError();
|
||||
handleReturnCode();
|
||||
}
|
||||
|
||||
abstract void handleStartCopy() throws RemoteException;
|
||||
abstract void handleServiceError();
|
||||
abstract void handleReturnCode();
|
||||
@@ -4969,15 +5102,20 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
int flags;
|
||||
final Uri packageURI;
|
||||
final String installerPackageName;
|
||||
final Uri verificationURI;
|
||||
final ManifestDigest manifestDigest;
|
||||
private InstallArgs mArgs;
|
||||
private int mRet;
|
||||
|
||||
InstallParams(Uri packageURI,
|
||||
IPackageInstallObserver observer, int flags,
|
||||
String installerPackageName) {
|
||||
String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) {
|
||||
this.packageURI = packageURI;
|
||||
this.flags = flags;
|
||||
this.observer = observer;
|
||||
this.installerPackageName = installerPackageName;
|
||||
this.verificationURI = verificationURI;
|
||||
this.manifestDigest = manifestDigest;
|
||||
}
|
||||
|
||||
private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
|
||||
@@ -5102,13 +5240,70 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Create the file args now.
|
||||
mArgs = createInstallArgs(this);
|
||||
|
||||
final InstallArgs args = createInstallArgs(this);
|
||||
if (ret == PackageManager.INSTALL_SUCCEEDED) {
|
||||
// Create copy only if we are not in an erroneous state.
|
||||
// Remote call to initiate copy using temporary file
|
||||
ret = mArgs.copyApk(mContainerService, true);
|
||||
/*
|
||||
* Determine if we have any installed package verifiers. If we
|
||||
* do, then we'll defer to them to verify the packages.
|
||||
*/
|
||||
final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION,
|
||||
packageURI);
|
||||
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
|
||||
PackageManager.GET_DISABLED_COMPONENTS);
|
||||
if (isVerificationEnabled() && receivers.size() > 0) {
|
||||
if (DEBUG_INSTALL) {
|
||||
Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
|
||||
+ verification.toString());
|
||||
}
|
||||
|
||||
final int verificationId = mPendingVerificationToken++;
|
||||
|
||||
verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
|
||||
|
||||
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
|
||||
installerPackageName);
|
||||
|
||||
verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, flags);
|
||||
|
||||
if (verificationURI != null) {
|
||||
verification.putExtra(PackageManager.EXTRA_VERIFICATION_URI,
|
||||
verificationURI);
|
||||
}
|
||||
|
||||
mPendingVerification.append(verificationId, args);
|
||||
|
||||
/*
|
||||
* Send the intent to the registered verification agents,
|
||||
* but only start the verification timeout after the target
|
||||
* BroadcastReceivers have run.
|
||||
*/
|
||||
mContext.sendOrderedBroadcast(verification,
|
||||
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final Message msg = mHandler
|
||||
.obtainMessage(CHECK_PENDING_VERIFICATION);
|
||||
msg.arg1 = verificationId;
|
||||
mHandler.sendMessageDelayed(msg, getVerificationTimeout());
|
||||
}
|
||||
},
|
||||
null, 0, null, null);
|
||||
} else {
|
||||
// Create copy only if we are not in an erroneous state.
|
||||
// Remote call to initiate copy using temporary file
|
||||
mArgs = args;
|
||||
ret = args.copyApk(mContainerService, true);
|
||||
}
|
||||
} else {
|
||||
// There was an error, so let the processPendingInstall() break
|
||||
// the bad news... uh, through a call in handleReturnCode()
|
||||
mArgs = args;
|
||||
}
|
||||
|
||||
mRet = ret;
|
||||
}
|
||||
|
||||
@@ -5233,14 +5428,15 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final int flags;
|
||||
final Uri packageURI;
|
||||
final String installerPackageName;
|
||||
final ManifestDigest manifestDigest;
|
||||
|
||||
InstallArgs(Uri packageURI,
|
||||
IPackageInstallObserver observer, int flags,
|
||||
String installerPackageName) {
|
||||
InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
|
||||
String installerPackageName, ManifestDigest manifestDigest) {
|
||||
this.packageURI = packageURI;
|
||||
this.flags = flags;
|
||||
this.observer = observer;
|
||||
this.installerPackageName = installerPackageName;
|
||||
this.manifestDigest = manifestDigest;
|
||||
}
|
||||
|
||||
abstract void createCopyFile();
|
||||
@@ -5265,12 +5461,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
boolean created = false;
|
||||
|
||||
FileInstallArgs(InstallParams params) {
|
||||
super(params.packageURI, params.observer,
|
||||
params.flags, params.installerPackageName);
|
||||
super(params.packageURI, params.observer, params.flags, params.installerPackageName,
|
||||
params.manifestDigest);
|
||||
}
|
||||
|
||||
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
|
||||
super(null, null, 0, null);
|
||||
super(null, null, 0, null, null);
|
||||
File codeFile = new File(fullCodePath);
|
||||
installDir = codeFile.getParentFile();
|
||||
codeFileName = fullCodePath;
|
||||
@@ -5279,7 +5475,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
|
||||
super(packageURI, null, 0, null);
|
||||
super(packageURI, null, 0, null, null);
|
||||
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
|
||||
String apkName = getNextCodePath(null, pkgName, ".apk");
|
||||
codeFileName = new File(installDir, apkName + ".apk").getPath();
|
||||
@@ -5509,12 +5705,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
String libraryPath;
|
||||
|
||||
SdInstallArgs(InstallParams params) {
|
||||
super(params.packageURI, params.observer,
|
||||
params.flags, params.installerPackageName);
|
||||
super(params.packageURI, params.observer, params.flags, params.installerPackageName,
|
||||
params.manifestDigest);
|
||||
}
|
||||
|
||||
SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
|
||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null, null);
|
||||
// Extract cid from fullCodePath
|
||||
int eidx = fullCodePath.lastIndexOf("/");
|
||||
String subStr1 = fullCodePath.substring(0, eidx);
|
||||
@@ -5524,13 +5720,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
|
||||
SdInstallArgs(String cid) {
|
||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null);
|
||||
super(null, null, PackageManager.INSTALL_EXTERNAL, null, null);
|
||||
this.cid = cid;
|
||||
setCachePath(PackageHelper.getSdDir(cid));
|
||||
}
|
||||
|
||||
SdInstallArgs(Uri packageURI, String cid) {
|
||||
super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null);
|
||||
super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null, null);
|
||||
this.cid = cid;
|
||||
}
|
||||
|
||||
@@ -6152,6 +6348,26 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
res.returnCode = pp.getParseError();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the installer passed in a manifest digest, compare it now. */
|
||||
if (args.manifestDigest != null) {
|
||||
if (DEBUG_INSTALL) {
|
||||
final String parsedManifest = pkg.manifestDigest == null ? "null"
|
||||
: pkg.manifestDigest.toString();
|
||||
Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
|
||||
+ parsedManifest);
|
||||
}
|
||||
|
||||
if (!args.manifestDigest.equals(pkg.manifestDigest)) {
|
||||
res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
|
||||
return;
|
||||
}
|
||||
} else if (DEBUG_INSTALL) {
|
||||
final String parsedManifest = pkg.manifestDigest == null
|
||||
? "null" : pkg.manifestDigest.toString();
|
||||
Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
|
||||
}
|
||||
|
||||
// Get rid of all references to package scan path via parser.
|
||||
pp = null;
|
||||
String oldCodePath = null;
|
||||
|
||||
@@ -37,6 +37,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.ManifestDigest;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -533,4 +534,22 @@ public class MockPackageManager extends PackageManager {
|
||||
public void updateUserFlags(int id, int flags) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
|
||||
int flags, String installerPackageName, Uri verificationURI,
|
||||
ManifestDigest manifestDigest) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void verifyPendingInstall(int id, boolean verified, String failureMessage) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user