115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root/* 215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Copyright (C) 2010 The Android Open Source Project 315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * you may not use this file except in compliance with the License. 615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * You may obtain a copy of the License at 715a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 815a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * http://www.apache.org/licenses/LICENSE-2.0 915a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * 1015a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * Unless required by applicable law or agreed to in writing, software 1115a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1215a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1315a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * See the License for the specific language governing permissions and 1415a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root * limitations under the License. 1515a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root */ 1615a4d2ffd04dc6c70f2cd17dae12ac6bc14c69abKenny Root 17c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapupackage com.android.defcontainer; 18c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu 19f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Rootimport android.app.IntentService; 20742e790294b3441b79f715fe447069b63c6065dbJeff Sharkeyimport android.content.Context; 21c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.content.Intent; 22e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackbornimport android.content.pm.IPackageManager; 237767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackbornimport android.content.pm.PackageCleanItem; 24a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapuimport android.content.pm.PackageInfoLite; 25e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackbornimport android.content.pm.PackageManager; 265b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapuimport android.content.pm.PackageParser; 27be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkeyimport android.content.pm.PackageParser.PackageLite; 28275e085d5a42ced54bb79e40ff76c77539e7d82dJeff Sharkeyimport android.content.pm.PackageParser.PackageParserException; 29a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.content.res.ObbInfo; 30a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Rootimport android.content.res.ObbScanner; 319a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkeyimport android.os.Binder; 32752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkeyimport android.os.Environment.UserEnvironment; 33b18f899241231991e314c40990eb8e9f703732d4Jeff Sharkeyimport android.os.FileUtils; 34c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.os.IBinder; 35c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.os.ParcelFileDescriptor; 36c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.os.Process; 37c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.os.RemoteException; 38c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport android.os.ServiceManager; 391ebd74acf9977daa42133507e970dab88e08f0efKenny Rootimport android.util.Slog; 40c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu 4163d0a067997cecf9c6e97a17852f9b657bbba48eJeff Sharkeyimport com.android.internal.app.IMediaContainerService; 4263d0a067997cecf9c6e97a17852f9b657bbba48eJeff Sharkeyimport com.android.internal.content.PackageHelper; 43be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkeyimport com.android.internal.os.IParcelFileDescriptorFactory; 44be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkeyimport com.android.internal.util.ArrayUtils; 4563d0a067997cecf9c6e97a17852f9b657bbba48eJeff Sharkey 4657dcf5b177b56195421535938544f32d8b591b42Jeff Sharkeyimport libcore.io.IoUtils; 4757dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey 48c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport java.io.File; 49c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport java.io.FileInputStream; 50c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport java.io.IOException; 51c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapuimport java.io.InputStream; 52f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Rootimport java.io.OutputStream; 53ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 54be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey/** 55be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * Service that offers to inspect and copy files that may reside on removable 56be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * storage. This is designed to prevent the system process from holding onto 57be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * open files that cause the kernel to kill it when the underlying device is 58be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * removed. 59c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu */ 60e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackbornpublic class DefaultContainerService extends IntentService { 61c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu private static final String TAG = "DefContainer"; 62c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu 63be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey // TODO: migrate native code unpacking to always be a derivative work 64be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey 65c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() { 66ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /** 67be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * Copy package to the target location. 68ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * 69be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * @param packagePath absolute path to the package to be copied. Can be 70be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * a single monolithic APK file or a cluster directory 71be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * containing one or more APKs. 72ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * @return returns status code according to those in 73ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward * {@link PackageManager} 74c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu */ 7557dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey @Override 76be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey public int copyPackage(String packagePath, IParcelFileDescriptorFactory target) { 77be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey if (packagePath == null || target == null) { 78f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Root return PackageManager.INSTALL_FAILED_INVALID_URI; 79f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Root } 80f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Root 81be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey PackageLite pkg = null; 82f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Root try { 83be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final File packageFile = new File(packagePath); 84be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey pkg = PackageParser.parsePackageLite(packageFile, 0); 85be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey return copyPackageInner(pkg, target); 86be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } catch (PackageParserException | IOException | RemoteException e) { 87be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey Slog.w(TAG, "Failed to copy package at " + packagePath + ": " + e); 88f5121a9b802c6ddd3661ed5cae602380dbe67090Kenny Root return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 89c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 90c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 915b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu 92ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward /** 93be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * Parse given package and return minimal details. 946431d11cd420536aaa9d93ae510a3151ccc4df1dNarayan Kamath * 95be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * @param packagePath absolute path to the package to be copied. Can be 96be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * a single monolithic APK file or a cluster directory 97be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * containing one or more APKs. 985b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu */ 99275e085d5a42ced54bb79e40ff76c77539e7d82dJeff Sharkey @Override 100742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey public PackageInfoLite getMinimalPackageInfo(String packagePath, int flags, 101742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey String abiOverride) { 102742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final Context context = DefaultContainerService.this; 103ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 104742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey PackageInfoLite ret = new PackageInfoLite(); 105ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward if (packagePath == null) { 106ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward Slog.i(TAG, "Invalid package file " + packagePath); 107a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; 108a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu return ret; 1093602f76d417b0940a26f28b7ad892abcfe03ef7cSuchi Amalapurapu } 110ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 111be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final File packageFile = new File(packagePath); 112be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final PackageParser.PackageLite pkg; 113742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey final long sizeBytes; 114275e085d5a42ced54bb79e40ff76c77539e7d82dJeff Sharkey try { 115be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey pkg = PackageParser.parsePackageLite(packageFile, 0); 116f8bb2445ff28d64d12d81d91539bb419f69e7874Jeff Sharkey sizeBytes = PackageHelper.calculateInstalledSize(pkg, abiOverride); 117742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey } catch (PackageParserException | IOException e) { 118742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Failed to parse package at " + packagePath + ": " + e); 1191ebd74acf9977daa42133507e970dab88e08f0efKenny Root 120be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey if (!packageFile.exists()) { 1211ebd74acf9977daa42133507e970dab88e08f0efKenny Root ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI; 1221ebd74acf9977daa42133507e970dab88e08f0efKenny Root } else { 1231ebd74acf9977daa42133507e970dab88e08f0efKenny Root ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; 1241ebd74acf9977daa42133507e970dab88e08f0efKenny Root } 1251ebd74acf9977daa42133507e970dab88e08f0efKenny Root 126a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu return ret; 1275b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu } 128ceb1b0bfaea56251796b08c07b963de7403d84ebAnonymous Coward 1299a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey final int recommendedInstallLocation; 1309a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey final long token = Binder.clearCallingIdentity(); 1319a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey try { 1329a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey recommendedInstallLocation = PackageHelper.resolveInstallLocation(context, 1339a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey pkg.packageName, pkg.installLocation, sizeBytes, flags); 1349a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey } finally { 1359a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey Binder.restoreCallingIdentity(token); 1369a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey } 1379a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey 138a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu ret.packageName = pkg.packageName; 13988d2a3c0e1b4a8c53a489db5d627beb80b1b9957Jeff Sharkey ret.splitNames = pkg.splitNames; 1407767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn ret.versionCode = pkg.versionCode; 1413accca05ddcad9d0b1b313eae49f273e39121d3cDianne Hackborn ret.versionCodeMajor = pkg.versionCodeMajor; 14288d2a3c0e1b4a8c53a489db5d627beb80b1b9957Jeff Sharkey ret.baseRevisionCode = pkg.baseRevisionCode; 14388d2a3c0e1b4a8c53a489db5d627beb80b1b9957Jeff Sharkey ret.splitRevisionCodes = pkg.splitRevisionCodes; 144930d3af75f9e9663222f4c4a1d75b326cf811e35Kenny Root ret.installLocation = pkg.installLocation; 14505ca4c90644921df9193d92b2abdc81ef77e4a62Kenny Root ret.verifiers = pkg.verifiers; 1469a4a45762219f43903f54d5f29157dc6b3881557Jeff Sharkey ret.recommendedInstallLocation = recommendedInstallLocation; 147ff110bd61a69f7ed8602ae14b27f7befec76b2e7Narayan Kamath ret.multiArch = pkg.multiArch; 1481ebd74acf9977daa42133507e970dab88e08f0efKenny Root 149a2b6c3775ed6b8924232d6a01bae4a19740a15f8Suchi Amalapurapu return ret; 1505b993ce7bc29e43a3215a50ce6ce5d6550d4e5e2Suchi Amalapurapu } 1518a9ab24a5c9b595ac0268fcade4b5bbfe7c45c2dSuchi Amalapurapu 15257dcf5b177b56195421535938544f32d8b591b42Jeff Sharkey @Override 153a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root public ObbInfo getObbInfo(String filename) { 15405105f7abe02b2dff91d6260b3628c8b97816babKenny Root try { 15505105f7abe02b2dff91d6260b3628c8b97816babKenny Root return ObbScanner.getObbInfo(filename); 15605105f7abe02b2dff91d6260b3628c8b97816babKenny Root } catch (IOException e) { 1571ebd74acf9977daa42133507e970dab88e08f0efKenny Root Slog.d(TAG, "Couldn't get OBB info for " + filename); 15805105f7abe02b2dff91d6260b3628c8b97816babKenny Root return null; 15905105f7abe02b2dff91d6260b3628c8b97816babKenny Root } 160a02b8b05dd1e8b8cf169e1f89542ef835b11fc13Kenny Root } 161aa183e2c9a279cb6aef7dc77855facfae795b6f8Kenny Root 162aa183e2c9a279cb6aef7dc77855facfae795b6f8Kenny Root @Override 163183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn public void clearDirectory(String path) throws RemoteException { 164183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 165183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn 166183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn final File directory = new File(path); 167183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn if (directory.exists() && directory.isDirectory()) { 168183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn eraseFiles(directory); 169183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn } 170183ce028f10442dd6ada59de8fa531d690134663Dianne Hackborn } 171cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root 172be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey /** 173be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * Calculate estimated footprint of given package post-installation. 174be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * 175be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * @param packagePath absolute path to the package to be copied. Can be 176be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * a single monolithic APK file or a cluster directory 177be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey * containing one or more APKs. 178be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey */ 179cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root @Override 180f8bb2445ff28d64d12d81d91539bb419f69e7874Jeff Sharkey public long calculateInstalledSize(String packagePath, String abiOverride) 181f8bb2445ff28d64d12d81d91539bb419f69e7874Jeff Sharkey throws RemoteException { 182cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root final File packageFile = new File(packagePath); 183be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey final PackageParser.PackageLite pkg; 184cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root try { 185be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey pkg = PackageParser.parsePackageLite(packageFile, 0); 186f8bb2445ff28d64d12d81d91539bb419f69e7874Jeff Sharkey return PackageHelper.calculateInstalledSize(pkg, abiOverride); 187be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } catch (PackageParserException | IOException e) { 188742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey Slog.w(TAG, "Failed to calculate installed size: " + e); 189742e790294b3441b79f715fe447069b63c6065dbJeff Sharkey return Long.MAX_VALUE; 190cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root } 191cea3743499f4bb8e5f28a2e57686d7af313169c5Kenny Root } 192c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu }; 193c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu 194e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn public DefaultContainerService() { 195e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn super("DefaultContainerService"); 196e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn setIntentRedelivery(true); 197e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 198e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn 199e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn @Override 200e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn protected void onHandleIntent(Intent intent) { 201e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn if (PackageManager.ACTION_CLEAN_EXTERNAL_STORAGE.equals(intent.getAction())) { 202752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkey final IPackageManager pm = IPackageManager.Stub.asInterface( 203e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn ServiceManager.getService("package")); 204752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkey PackageCleanItem item = null; 205e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn try { 206752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkey while ((item = pm.nextPackageToClean(item)) != null) { 207752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkey final UserEnvironment userEnv = new UserEnvironment(item.userId); 2087f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey eraseFiles(userEnv.buildExternalStorageAppDataDirs(item.packageName)); 2097f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey eraseFiles(userEnv.buildExternalStorageAppMediaDirs(item.packageName)); 210752cd922f7091dfd5401faf70dc248934a9dbb6dJeff Sharkey if (item.andCode) { 2117f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey eraseFiles(userEnv.buildExternalStorageAppObbDirs(item.packageName)); 2127767eac3232ba2fb9828766813cdb481d6a97584Dianne Hackborn } 213e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 214e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } catch (RemoteException e) { 215e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 216e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 217e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 218e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn 2197f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey void eraseFiles(File[] paths) { 2207f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey for (File path : paths) { 2217f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey eraseFiles(path); 2227f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey } 2237f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey } 2247f392defccfae54dc8169e5ad82c2616e0713c8eJeff Sharkey 225e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn void eraseFiles(File path) { 226e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn if (path.isDirectory()) { 227e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn String[] files = path.list(); 228e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn if (files != null) { 229e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn for (String file : files) { 230e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn eraseFiles(new File(path, file)); 231e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 232e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 233e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 234e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn path.delete(); 235e83cefcef07f9ac025642c1ffec76b4c7ab39cf2Dianne Hackborn } 236be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey 237be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey @Override 238c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu public IBinder onBind(Intent intent) { 239c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu return mBinder; 240c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu } 241c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu 242be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey private int copyPackageInner(PackageLite pkg, IParcelFileDescriptorFactory target) 243be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey throws IOException, RemoteException { 244bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyFile(pkg.baseCodePath, target, "base.apk"); 245be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey if (!ArrayUtils.isEmpty(pkg.splitNames)) { 246d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey for (int i = 0; i < pkg.splitNames.length; i++) { 247bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey copyFile(pkg.splitCodePaths[i], target, "split_" + pkg.splitNames[i] + ".apk"); 248d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey } 249be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } 250be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey 251d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey return PackageManager.INSTALL_SUCCEEDED; 252d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey } 253d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey 254bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey private void copyFile(String sourcePath, IParcelFileDescriptorFactory target, String targetName) 255bb7b7bea19223c1eba74f525c7fe87ca3911813bJeff Sharkey throws IOException, RemoteException { 256d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey Slog.d(TAG, "Copying " + sourcePath + " to " + targetName); 257be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey InputStream in = null; 258be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey OutputStream out = null; 259be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey try { 260d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey in = new FileInputStream(sourcePath); 261be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey out = new ParcelFileDescriptor.AutoCloseOutputStream( 262d746057f2414cba2bdc69257cc5be8cb681bb592Jeff Sharkey target.open(targetName, ParcelFileDescriptor.MODE_READ_WRITE)); 263b18f899241231991e314c40990eb8e9f703732d4Jeff Sharkey FileUtils.copy(in, out); 264be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } finally { 265be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey IoUtils.closeQuietly(out); 266be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey IoUtils.closeQuietly(in); 267be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } 268be520fba1e45c77ca20eb66005a0cf19e10939a1Jeff Sharkey } 269c028be4f3b8c7476b46859f66c3f33d528adf181Suchi Amalapurapu} 270