14c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse/* 24c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * Copyright 2014, The Android Open Source Project 34c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * 44c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * Licensed under the Apache License, Version 2.0 (the "License"); 54c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * you may not use this file except in compliance with the License. 64c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * You may obtain a copy of the License at 74c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * 84c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * http://www.apache.org/licenses/LICENSE-2.0 94c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * 104c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * Unless required by applicable law or agreed to in writing, software 114c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * distributed under the License is distributed on an "AS IS" BASIS, 124c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * See the License for the specific language governing permissions and 144c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * limitations under the License. 154c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse */ 164c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnsepackage com.android.managedprovisioning.task; 174c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 184c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.app.DownloadManager; 194c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.content.Context; 204c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.content.pm.IPackageInstallObserver; 214c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.content.pm.ActivityInfo; 224c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.content.pm.PackageInfo; 234c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.content.pm.PackageManager; 244c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.net.Uri; 250080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnseimport android.provider.Settings.Global; 264c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.text.TextUtils; 274c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport android.Manifest.permission; 284c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 294c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport com.android.managedprovisioning.ProvisionLogger; 304c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 314c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnseimport java.io.File; 324c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 334c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse/** 344c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * Installs a device owner package from a given path. 354c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * <p> 364c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * Before installing it is checked whether the file at the specified path contains the given package 374c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * and the given admin receiver. 384c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse * </p> 394c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse */ 404c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnsepublic class InstallPackageTask { 414c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public static final int ERROR_PACKAGE_INVALID = 0; 424c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public static final int ERROR_INSTALLATION_FAILED = 1; 434c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 4428bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse private final Context mContext; 4528bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse private final Callback mCallback; 4628bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse private final String mPackageName; 4728bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse 484c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse private String mPackageLocation; 494c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse private PackageManager mPm; 500080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse private int mPackageVerifierEnable; 514c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 52cdf13b1826bd84f7d5c11ba14d14eb4889c2dda8Sander Alewijnse public InstallPackageTask (Context context, String packageName, 5328bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse Callback callback) { 5428bffd6424a3d9f2dbefe6c7d6144f3a4edee3bcSander Alewijnse mCallback = callback; 554c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mContext = context; 564c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mPackageLocation = null; // Initialized in run(). 574c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mPackageName = packageName; 584c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 594c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 60d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse public void run(String packageLocation) { 614c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse if (TextUtils.isEmpty(packageLocation)) { 624c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ProvisionLogger.loge("Package Location is empty."); 634c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onError(ERROR_PACKAGE_INVALID); 644c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse return; 654c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 664c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mPackageLocation = packageLocation; 674c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 684c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse PackageInstallObserver observer = new PackageInstallObserver(); 694c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mPm = mContext.getPackageManager(); 704c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 714c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse if (packageContentIsCorrect()) { 72bdd8d3f865e51915fb11776d21ac2fb2888e0f22Sander Alewijnse // Temporarily turn off package verification. 730080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse mPackageVerifierEnable = Global.getInt(mContext.getContentResolver(), 740080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse Global.PACKAGE_VERIFIER_ENABLE, 1); 750080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse Global.putInt(mContext.getContentResolver(), Global.PACKAGE_VERIFIER_ENABLE, 0); 760080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse 778c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse Uri packageUri = Uri.parse("file://" + mPackageLocation); 788c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse 794c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse // Allow for replacing an existing package. 804c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse // Needed in case this task is performed multiple times. 818c664076cc8e08985c58e9da8d85ab162c9533efSander Alewijnse mPm.installPackage(packageUri, observer, 824c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse /* flags */ PackageManager.INSTALL_REPLACE_EXISTING, mContext.getPackageName()); 834c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } else { 844c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse // Error should have been reported in packageContentIsCorrect(). 854c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse return; 864c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 874c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 884c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 894c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse private boolean packageContentIsCorrect() { 904c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse PackageInfo pi = mPm.getPackageArchiveInfo(mPackageLocation, 914c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse PackageManager.GET_RECEIVERS); 924c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse if (pi == null) { 934c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ProvisionLogger.loge("Package could not be parsed successfully."); 944c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onError(ERROR_PACKAGE_INVALID); 954c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse return false; 964c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 974c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse if (!pi.packageName.equals(mPackageName)) { 984c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ProvisionLogger.loge("Package name in apk (" + pi.packageName 994c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse + ") does not match package name specified by programmer (" 1004c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse + mPackageName + ")."); 1014c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onError(ERROR_PACKAGE_INVALID); 1024c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse return false; 1034c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1044c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse for (ActivityInfo ai : pi.receivers) { 1054c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse if (!TextUtils.isEmpty(ai.permission) && 1064c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) { 107cdf13b1826bd84f7d5c11ba14d14eb4889c2dda8Sander Alewijnse return true; 1084c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1094c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1104c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ProvisionLogger.loge("Installed package has no admin receiver."); 1114c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onError(ERROR_PACKAGE_INVALID); 1124c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse return false; 1134c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1144c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 1154c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse private class PackageInstallObserver extends IPackageInstallObserver.Stub { 1164c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse @Override 1174c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public void packageInstalled(String packageName, int returnCode) { 118bdd8d3f865e51915fb11776d21ac2fb2888e0f22Sander Alewijnse // Set package verification flag to its original value. 1190080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse Global.putInt(mContext.getContentResolver(), Global.PACKAGE_VERIFIER_ENABLE, 1200080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse mPackageVerifierEnable); 1210080f2afbafe0ed837bb2778a7a36357a0c42946Sander Alewijnse 12223d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse if (returnCode == PackageManager.INSTALL_SUCCEEDED 12323d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse && mPackageName.equals(packageName)) { 12423d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse ProvisionLogger.logd("Package " + mPackageName + " is succesfully installed."); 125d70438542632a1c8df15bdd9d91bfee52bf2b655Sander Alewijnse 1264c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onSuccess(); 1274c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } else { 12823d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse if (returnCode == PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE) { 12923d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse ProvisionLogger.logd("Current version of " + mPackageName 13023d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse + " higher than the version to be installed."); 13123d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse ProvisionLogger.logd("Package " + mPackageName + " was not reinstalled."); 13223d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse mCallback.onSuccess(); 13323d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse return; 13423d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse } 13523d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse 13623d457375fbcb1488b7b5d5e5c0d7a4cca78c77bSander Alewijnse ProvisionLogger.logd("Installing package " + mPackageName + " failed."); 1374c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse ProvisionLogger.logd("Errorcode returned by IPackageInstallObserver = " 1384c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse + returnCode); 1394c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse mCallback.onError(ERROR_INSTALLATION_FAILED); 1404c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1414c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1424c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1434c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse 1444c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public abstract static class Callback { 1454c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public abstract void onSuccess(); 1464c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse public abstract void onError(int errorCode); 1474c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse } 1484c4badfbd6a9271297c12a7db495ca2e7bd7734dSander Alewijnse}