private int createSessionInternal(SessionParams params, String installerPackageName, int userId) throws IOException { final int callingUid = VBinder.getCallingUid(); final int sessionId; final PackageInstallerSession session; synchronized (mSessions) { // Sanity check that installer isn't going crazy final int activeCount = getSessionCount(mSessions, callingUid); if (activeCount >= MAX_ACTIVE_SESSIONS) { throw new IllegalStateException( "Too many active sessions for UID " + callingUid); } sessionId = allocateSessionIdLocked(); session = new PackageInstallerSession(mInternalCallback, mContext, mInstallHandler.getLooper(), installerPackageName, sessionId, userId, callingUid, params, VEnvironment.getPackageInstallerStageDir()); } mCallbacks.notifySessionCreated(session.sessionId, session.userId); return sessionId; }
@Override public void abandonSession(int sessionId) throws RemoteException { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); if (session == null || !isCallingUidOwner(session)) { throw new SecurityException("Caller has no access to session " + sessionId); } session.abandon(); } }
@Override public String[] getNames() throws RemoteException { assertPreparedAndNotSealed("getNames"); try { return resolveStageDir().list(); } catch (IOException e) { throw new IllegalStateException(e); } }
@Override public void abandon() throws RemoteException { destroyInternal(); dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); }
private void commitLocked() throws PackageManagerException { if (mDestroyed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed"); } if (!mSealed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed"); } try { resolveStageDir(); } catch (IOException e) { e.printStackTrace(); } validateInstallLocked(); mInternalProgress = 0.5f; computeProgressLocked(true); // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { throw new IllegalStateException(); } @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { destroyInternal(); dispatchSessionFinished(returnCode, msg, extras); } }; }
@Override public SessionInfo getSessionInfo(int sessionId) throws RemoteException { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); return session != null ? session.generateInfo() : null; } }
@Override public void setClientProgress(float progress) throws RemoteException { synchronized (mLock) { // Always publish first staging movement final boolean forcePublish = (mClientProgress == 0); mClientProgress = progress; computeProgressLocked(forcePublish); } }
@Override public void removeSplit(String splitName) throws RemoteException { if (TextUtils.isEmpty(params.appPackageName)) { throw new IllegalStateException("Must specify package name to remove a split"); } try { createRemoveSplitMarker(splitName); } catch (IOException e) { throw new IllegalStateException(e); } }
private void computeProgressLocked(boolean forcePublish) { mProgress = constrain(mClientProgress * 0.8f, 0f, 0.8f) + constrain(mInternalProgress * 0.2f, 0f, 0.2f); // Only publish when meaningful change if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) { mReportedProgress = mProgress; mCallback.onSessionProgressChanged(this, mProgress); } }
@Override public boolean handleMessage(Message msg) { synchronized (mLock) { if (msg.obj != null) { mRemoteObserver = (IPackageInstallObserver2) msg.obj; } try { commitLocked(); } catch (PackageManagerException e) { final String completeMsg = getCompleteMessage(e); VLog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg); destroyInternal(); dispatchSessionFinished(e.error, completeMsg, null); } return true; } } };
private void commitLocked() throws PackageManagerException { if (mDestroyed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed"); } if (!mSealed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed"); } try { resolveStageDir(); } catch (IOException e) { e.printStackTrace(); } validateInstallLocked(); mInternalProgress = 0.5f; computeProgressLocked(true); // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { throw new IllegalStateException(); } @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { destroyInternal(); dispatchSessionFinished(returnCode, msg, extras); } }; }
void setPermissionsResult(boolean accepted) { if (!mSealed) { throw new SecurityException("Must be sealed to accept permissions"); } if (accepted) { // Mark and kick off another install pass synchronized (mLock) { mPermissionsAccepted = true; } mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); } else { destroyInternal(); dispatchSessionFinished(INSTALL_FAILED_ABORTED, "User rejected permissions", null); } }
@Override public VParceledListSlice getAllSessions(int userId) throws RemoteException { final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); if (session.userId == userId) { result.add(session.generateInfo()); } } } return new VParceledListSlice<>(result); }
@Override public void removeSplit(String splitName) throws RemoteException { if (TextUtils.isEmpty(params.appPackageName)) { throw new IllegalStateException("Must specify package name to remove a split"); } try { createRemoveSplitMarker(splitName); } catch (IOException e) { throw new IllegalStateException(e); } }
private void computeProgressLocked(boolean forcePublish) { mProgress = constrain(mClientProgress * 0.8f, 0f, 0.8f) + constrain(mInternalProgress * 0.2f, 0f, 0.2f); // Only publish when meaningful change if (forcePublish || Math.abs(mProgress - mReportedProgress) >= 0.01) { mReportedProgress = mProgress; mCallback.onSessionProgressChanged(this, mProgress); } }
@Override public boolean handleMessage(Message msg) { synchronized (mLock) { if (msg.obj != null) { mRemoteObserver = (IPackageInstallObserver2) msg.obj; } try { commitLocked(); } catch (PackageManagerException e) { final String completeMsg = getCompleteMessage(e); VLog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg); destroyInternal(); dispatchSessionFinished(e.error, completeMsg, null); } return true; } } };
private ParcelFileDescriptor openReadInternal(String name) throws IOException { assertPreparedAndNotSealed("openRead"); try { if (!FileUtils.isValidExtFilename(name)) { throw new IllegalArgumentException("Invalid name: " + name); } final File target = new File(resolveStageDir(), name); final FileDescriptor targetFd = Os.open(target.getAbsolutePath(), O_RDONLY, 0); return ParcelFileDescriptor.dup(targetFd); } catch (ErrnoException e) { throw new IOException(e); } }
private void commitLocked() throws PackageManagerException { if (mDestroyed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed"); } if (!mSealed) { throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed"); } try { resolveStageDir(); } catch (IOException e) { e.printStackTrace(); } validateInstallLocked(); mInternalProgress = 0.5f; computeProgressLocked(true); // We've reached point of no return; call into PMS to install the stage. // Regardless of success or failure we always destroy session. final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() { @Override public void onUserActionRequired(Intent intent) { throw new IllegalStateException(); } @Override public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { destroyInternal(); dispatchSessionFinished(returnCode, msg, extras); } }; }
@Override public void abandon() throws RemoteException { destroyInternal(); dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); }