PackageInstallerSession.java revision a10311434778ea1be1621c2251c0c8c2966f337b
1d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi/* 2d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * Copyright (C) 2014 The Android Open Source Project 3d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * 4d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * you may not use this file except in compliance with the License. 6d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * You may obtain a copy of the License at 7d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * 8d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * 10d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * See the License for the specific language governing permissions and 14d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * limitations under the License. 15d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi */ 16d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 17d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivipackage com.android.server.pm; 18d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 19d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS; 20d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; 21d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; 22d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; 23d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.system.OsConstants.O_CREAT; 24d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport static android.system.OsConstants.O_WRONLY; 25d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 26d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.ApplicationInfo; 27d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.IPackageInstallObserver2; 28d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.IPackageInstallerSession; 29d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.InstallSessionInfo; 30d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.InstallSessionParams; 31d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.PackageManager; 32d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.PackageParser; 33d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.PackageParser.ApkLite; 34d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.PackageParser.PackageParserException; 35d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.content.pm.Signature; 36d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.Bundle; 37d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.FileBridge; 38d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.FileUtils; 39d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.Handler; 40d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.Looper; 41d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.Message; 42d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.ParcelFileDescriptor; 43d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.Process; 44d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.RemoteException; 45d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.os.UserHandle; 46d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.system.ErrnoException; 47d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.system.Os; 48d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.system.OsConstants; 49d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.system.StructStat; 50d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.util.ArraySet; 51d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.util.ExceptionUtils; 52d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.util.MathUtils; 53d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport android.util.Slog; 54d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 55d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport com.android.internal.util.ArrayUtils; 56d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport com.android.internal.util.IndentingPrintWriter; 57d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport com.android.internal.util.Preconditions; 58d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 59d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport libcore.io.Libcore; 60d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 61d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport java.io.File; 62d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport java.io.FileDescriptor; 63d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport java.io.IOException; 64d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Triviimport java.util.ArrayList; 65d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 66d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivipublic class PackageInstallerSession extends IPackageInstallerSession.Stub { 67d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private static final String TAG = "PackageInstaller"; 68d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 69d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: enforce INSTALL_ALLOW_TEST 70d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: enforce INSTALL_ALLOW_DOWNGRADE 71d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: handle INSTALL_EXTERNAL, INSTALL_INTERNAL 72d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 73d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private final PackageInstallerService.Callback mCallback; 74d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private final PackageManagerService mPm; 75d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private final Handler mHandler; 76d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 77d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final int sessionId; 78d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final int userId; 79d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final String installerPackageName; 80d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi /** UID not persisted */ 81d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final int installerUid; 82d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final InstallSessionParams params; 83d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final long createdMillis; 84d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public final File sessionStageDir; 85d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 86d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private static final int MSG_INSTALL = 0; 87d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 88d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private Handler.Callback mHandlerCallback = new Handler.Callback() { 89d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 90d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public boolean handleMessage(Message msg) { 91d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi synchronized (mLock) { 92d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (msg.obj != null) { 93d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mRemoteObserver = (IPackageInstallObserver2) msg.obj; 94d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 95d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 96d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 97d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi installLocked(); 98d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (PackageManagerException e) { 99d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Slog.e(TAG, "Install failed: " + e); 100d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi destroyInternal(); 101d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 102d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mRemoteObserver.packageInstalled(mPackageName, null, e.error, 103d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi e.getMessage()); 104d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (RemoteException ignored) { 105d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 106d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mCallback.onSessionFinished(PackageInstallerSession.this, false); 107d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 108d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 109d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi return true; 110d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 111d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 112d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi }; 113d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 114d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private final Object mLock = new Object(); 115d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 116d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private int mClientProgress; 117d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private int mProgress = 0; 118d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 119d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private String mPackageName; 120d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private int mVersionCode; 121d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private Signature[] mSignatures; 122d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 123d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private boolean mMutationsAllowed; 124d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private boolean mPermissionsConfirmed; 125d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private boolean mInvalid; 126d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 127d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private ArrayList<FileBridge> mBridges = new ArrayList<>(); 128d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 129d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private IPackageInstallObserver2 mRemoteObserver; 130d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 131d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public PackageInstallerSession(PackageInstallerService.Callback callback, 132d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi PackageManagerService pm, int sessionId, int userId, String installerPackageName, 133d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi int installerUid, InstallSessionParams params, long createdMillis, File sessionStageDir, 134d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Looper looper) { 135d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mCallback = callback; 136d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPm = pm; 137d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mHandler = new Handler(looper, mHandlerCallback); 138d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 139d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.sessionId = sessionId; 140d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.userId = userId; 141d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.installerPackageName = installerPackageName; 142d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.installerUid = installerUid; 143d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.params = params; 144d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.createdMillis = createdMillis; 145d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi this.sessionStageDir = sessionStageDir; 146d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 147d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Check against any explicitly provided signatures 148d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mSignatures = params.signatures; 149d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 150d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: splice in flag when restoring persisted session 151d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mMutationsAllowed = true; 152d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 153d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (pm.checkPermission(android.Manifest.permission.INSTALL_PACKAGES, installerPackageName) 154d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi == PackageManager.PERMISSION_GRANTED) { 155d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPermissionsConfirmed = true; 156d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 157d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (installerUid == Process.SHELL_UID || installerUid == 0) { 158d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPermissionsConfirmed = true; 159d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 160d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 161d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 162d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public InstallSessionInfo generateInfo() { 163d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final InstallSessionInfo info = new InstallSessionInfo(); 164d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 165d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.sessionId = sessionId; 166d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.installerPackageName = installerPackageName; 167d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.progress = mProgress; 168d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 169d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.fullInstall = params.fullInstall; 170d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.packageName = params.packageName; 171d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.icon = params.icon; 172d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.title = params.title; 173d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 174d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi return info; 175d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 176d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 177d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 178d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public void setClientProgress(int progress) { 179d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mClientProgress = progress; 180d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mProgress = MathUtils.constrain((mClientProgress * 8 * 100) / (params.progressMax * 10), 0, 80); 181d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mCallback.onSessionProgress(this, mProgress); 182d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 183d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 184d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 185d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public void addClientProgress(int progress) { 186d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi setClientProgress(mClientProgress + progress); 187d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 188d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 189d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 190d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes) { 191d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 192d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi return openWriteInternal(name, offsetBytes, lengthBytes); 193d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (IOException e) { 194d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw ExceptionUtils.wrap(e); 195d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 196d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 197d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 198d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private ParcelFileDescriptor openWriteInternal(String name, long offsetBytes, long lengthBytes) 199d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throws IOException { 200d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: relay over to DCS when installing to ASEC 201d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 202d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Quick sanity check of state, and allocate a pipe for ourselves. We 203d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // then do heavy disk allocation outside the lock, but this open pipe 204d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // will block any attempted install transitions. 205d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final FileBridge bridge; 206d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi synchronized (mLock) { 207d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!mMutationsAllowed) { 208d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new IllegalStateException("Mutations not allowed"); 209d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 210d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 211d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi bridge = new FileBridge(); 212d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mBridges.add(bridge); 213d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 214d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 215d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 216d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Use installer provided name for now; we always rename later 217d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!FileUtils.isValidExtFilename(name)) { 218d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new IllegalArgumentException("Invalid name: " + name); 219d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 220d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final File target = new File(sessionStageDir, name); 221d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 222d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final FileDescriptor targetFd = Libcore.os.open(target.getAbsolutePath(), 223d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi O_CREAT | O_WRONLY, 0644); 224d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Os.chmod(target.getAbsolutePath(), 0644); 225d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 226d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // If caller specified a total length, allocate it for them. Free up 227d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // cache space to grow, if needed. 228d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (lengthBytes > 0) { 229d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final StructStat stat = Libcore.os.fstat(targetFd); 230d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final long deltaBytes = lengthBytes - stat.st_size; 231d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (deltaBytes > 0) { 232d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPm.freeStorage(deltaBytes); 233d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 234d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Libcore.os.posix_fallocate(targetFd, 0, lengthBytes); 235d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 236d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 237d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (offsetBytes > 0) { 238d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Libcore.os.lseek(targetFd, offsetBytes, OsConstants.SEEK_SET); 239d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 240d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 241d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi bridge.setTargetFile(targetFd); 242d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi bridge.start(); 243d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi return new ParcelFileDescriptor(bridge.getClientSocket()); 244d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 245d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (ErrnoException e) { 246d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw e.rethrowAsIOException(); 247d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 248d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 249d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 250d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 251d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public void install(IPackageInstallObserver2 observer) { 252d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Preconditions.checkNotNull(observer); 253d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mHandler.obtainMessage(MSG_INSTALL, observer).sendToTarget(); 254d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 255d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 256d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private void installLocked() throws PackageManagerException { 257d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (mInvalid) { 258d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new PackageManagerException(INSTALL_FAILED_ALREADY_EXISTS, "Invalid session"); 259d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 260d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 261d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Verify that all writers are hands-off 262d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (mMutationsAllowed) { 263d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi for (FileBridge bridge : mBridges) { 264d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!bridge.isClosed()) { 265d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED, 266d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi "Files still open"); 267d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 268d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 269d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mMutationsAllowed = false; 270d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 271d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: persist disabled mutations before going forward, since 272d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // beyond this point we may have hardlinks to the valid install 273d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 274d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 275d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Verify that stage looks sane with respect to existing application. 276d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // This currently only ensures packageName, versionCode, and certificate 277d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // consistency. 278d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi validateInstallLocked(); 279d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 280d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Preconditions.checkNotNull(mPackageName); 281d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi Preconditions.checkNotNull(mSignatures); 282d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 283d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!mPermissionsConfirmed) { 284d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: async confirm permissions with user 285d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // when they confirm, we'll kick off another install() pass 286d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new SecurityException("Caller must hold INSTALL permission"); 287d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 288d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 289d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Inherit any packages and native libraries from existing install that 290d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // haven't been overridden. 291d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!params.fullInstall) { 292d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi spliceExistingFilesIntoStage(); 293d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 294d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 295d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: surface more granular state from dexopt 296d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mCallback.onSessionProgress(this, 90); 297d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 298d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // TODO: for ASEC based applications, grow and stream in packages 299d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 300d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // We've reached point of no return; call into PMS to install the stage. 301d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Regardless of success or failure we always destroy session. 302d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final IPackageInstallObserver2 remoteObserver = mRemoteObserver; 303d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { 304d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi @Override 305d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi public void packageInstalled(String basePackageName, Bundle extras, int returnCode, 306d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi String msg) { 307d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi destroyInternal(); 308d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 309d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi remoteObserver.packageInstalled(basePackageName, extras, returnCode, msg); 310d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (RemoteException ignored) { 311d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 312d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED); 313d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mCallback.onSessionFinished(PackageInstallerSession.this, success); 314d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 315d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi }; 316d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 317d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPm.installStage(mPackageName, this.sessionStageDir, localObserver, params, 318d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi installerPackageName, installerUid, new UserHandle(userId)); 319d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 320d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 321d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi /** 322d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * Validate install by confirming that all application packages are have 323d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * consistent package name, version code, and signing certificates. 324d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * <p> 325d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi * Renames package files in stage to match split names defined inside. 326d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi */ 327d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi private void validateInstallLocked() throws PackageManagerException { 328d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPackageName = null; 329d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mVersionCode = -1; 330d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 331d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final File[] files = sessionStageDir.listFiles(); 332d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (ArrayUtils.isEmpty(files)) { 333d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged"); 334d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 335d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 336d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final ArraySet<String> seenSplits = new ArraySet<>(); 337d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 338d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Verify that all staged packages are internally consistent 339d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi for (File file : files) { 340d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final ApkLite info; 341d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi try { 342d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info = PackageParser.parseApkLite(file, PackageParser.PARSE_GET_SIGNATURES); 343d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } catch (PackageParserException e) { 344d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 345d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi "Failed to parse " + file + ": " + e); 346d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 347d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 348d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!seenSplits.add(info.splitName)) { 349d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 350d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi "Split " + info.splitName + " was defined multiple times"); 351d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 352d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 353d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Use first package to define unknown values 354d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (mPackageName == null) { 355d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mPackageName = info.packageName; 356d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mVersionCode = info.versionCode; 357d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 358d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (mSignatures == null) { 359d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi mSignatures = info.signatures; 360d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 361d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 362d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi assertPackageConsistent(String.valueOf(file), info.packageName, info.versionCode, 363d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi info.signatures); 364d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi 365d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi // Take this opportunity to enforce uniform naming 366d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi final String name; 367d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (info.splitName == null) { 368d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi name = "base.apk"; 369d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } else { 370d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi name = "split_" + info.splitName + ".apk"; 371d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi } 372d4838ed14a169f5981c0adc2edcb24559a913fe6Jean-Michel Trivi if (!FileUtils.isValidExtFilename(name)) { 373 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 374 "Invalid filename: " + name); 375 } 376 if (!file.getName().equals(name)) { 377 file.renameTo(new File(file.getParentFile(), name)); 378 } 379 } 380 381 // TODO: shift package signature verification to installer; we're 382 // currently relying on PMS to do this. 383 // TODO: teach about compatible upgrade keysets. 384 385 if (params.fullInstall) { 386 // Full installs must include a base package 387 if (!seenSplits.contains(null)) { 388 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 389 "Full install must include a base package"); 390 } 391 392 } else { 393 // Partial installs must be consistent with existing install. 394 final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId); 395 if (app == null) { 396 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 397 "Missing existing base package for " + mPackageName); 398 } 399 400 final ApkLite info; 401 try { 402 info = PackageParser.parseApkLite(new File(app.getBaseCodePath()), 403 PackageParser.PARSE_GET_SIGNATURES); 404 } catch (PackageParserException e) { 405 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 406 "Failed to parse existing base " + app.getBaseCodePath() + ": " + e); 407 } 408 409 assertPackageConsistent("Existing base", info.packageName, info.versionCode, 410 info.signatures); 411 } 412 } 413 414 private void assertPackageConsistent(String tag, String packageName, int versionCode, 415 Signature[] signatures) throws PackageManagerException { 416 if (!mPackageName.equals(packageName)) { 417 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag + " package " 418 + packageName + " inconsistent with " + mPackageName); 419 } 420 if (mVersionCode != versionCode) { 421 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, tag 422 + " version code " + versionCode + " inconsistent with " 423 + mVersionCode); 424 } 425 if (!Signature.areExactMatch(mSignatures, signatures)) { 426 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 427 tag + " signatures are inconsistent"); 428 } 429 } 430 431 /** 432 * Application is already installed; splice existing files that haven't been 433 * overridden into our stage. 434 */ 435 private void spliceExistingFilesIntoStage() throws PackageManagerException { 436 final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId); 437 final File existingDir = new File(app.getBaseCodePath()); 438 439 try { 440 linkTreeIgnoringExisting(existingDir, sessionStageDir); 441 } catch (ErrnoException e) { 442 throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, 443 "Failed to splice into stage"); 444 } 445 } 446 447 /** 448 * Recursively hard link all files from source directory tree to target. 449 * When a file already exists in the target tree, it leaves that file 450 * intact. 451 */ 452 private void linkTreeIgnoringExisting(File sourceDir, File targetDir) throws ErrnoException { 453 final File[] sourceContents = sourceDir.listFiles(); 454 if (ArrayUtils.isEmpty(sourceContents)) return; 455 456 for (File sourceFile : sourceContents) { 457 final File targetFile = new File(targetDir, sourceFile.getName()); 458 459 if (sourceFile.isDirectory()) { 460 targetFile.mkdir(); 461 linkTreeIgnoringExisting(sourceFile, targetFile); 462 } else { 463 Libcore.os.link(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath()); 464 } 465 } 466 } 467 468 @Override 469 public void destroy() { 470 try { 471 destroyInternal(); 472 } finally { 473 mCallback.onSessionFinished(this, false); 474 } 475 } 476 477 private void destroyInternal() { 478 synchronized (mLock) { 479 mInvalid = true; 480 } 481 FileUtils.deleteContents(sessionStageDir); 482 sessionStageDir.delete(); 483 } 484 485 void dump(IndentingPrintWriter pw) { 486 pw.println("Session " + sessionId + ":"); 487 pw.increaseIndent(); 488 489 pw.printPair("userId", userId); 490 pw.printPair("installerPackageName", installerPackageName); 491 pw.printPair("installerUid", installerUid); 492 pw.printPair("createdMillis", createdMillis); 493 pw.printPair("sessionStageDir", sessionStageDir); 494 pw.println(); 495 496 params.dump(pw); 497 498 pw.printPair("mClientProgress", mClientProgress); 499 pw.printPair("mProgress", mProgress); 500 pw.printPair("mMutationsAllowed", mMutationsAllowed); 501 pw.printPair("mPermissionsConfirmed", mPermissionsConfirmed); 502 pw.printPair("mBridges", mBridges.size()); 503 pw.println(); 504 505 pw.decreaseIndent(); 506 } 507} 508