1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
20 
21 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
22 import static com.android.server.pm.PackageManagerService.TAG;
23 
24 import android.content.pm.IPackageInstallObserver2;
25 import android.content.pm.PackageManager;
26 import android.os.Bundle;
27 import android.os.RemoteException;
28 import android.os.Trace;
29 import android.os.UserHandle;
30 import android.util.ArraySet;
31 import android.util.Slog;
32 
33 import java.util.List;
34 import java.util.Set;
35 
36 /**
37  * Container for a multi-package verifying session which refers to all verifying sessions and args
38  * being committed together.
39  */
40 final class MultiPackageVerifyingSession {
41     private final IPackageInstallObserver2 mObserver;
42     private final List<VerifyingSession> mChildVerifyingSessions;
43     private final Set<VerifyingSession> mVerificationState;
44     private final UserHandle mUser;
45 
MultiPackageVerifyingSession(VerifyingSession parent, List<VerifyingSession> children)46     MultiPackageVerifyingSession(VerifyingSession parent, List<VerifyingSession> children)
47             throws PackageManagerException {
48         mUser = parent.getUser();
49         if (children.size() == 0) {
50             throw PackageManagerException.ofInternalError("No child sessions found!",
51                     PackageManagerException.INTERNAL_ERROR_VERIFY_MISSING_CHILD_SESSIONS);
52         }
53         mChildVerifyingSessions = children;
54         // Provide every child with reference to this object as parent
55         for (int i = 0; i < children.size(); i++) {
56             final VerifyingSession childVerifyingSession = children.get(i);
57             childVerifyingSession.mParentVerifyingSession = this;
58         }
59         mVerificationState = new ArraySet<>(mChildVerifyingSessions.size());
60         mObserver = parent.mObserver;
61     }
62 
start()63     public void start() {
64         if (DEBUG_INSTALL) Slog.i(TAG, "start " + mUser + ": " + this);
65         Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueVerify",
66                 System.identityHashCode(this));
67         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startVerify");
68         for (VerifyingSession childVerifyingSession : mChildVerifyingSessions) {
69             childVerifyingSession.handleStartVerify();
70         }
71         for (VerifyingSession childVerifyingSession : mChildVerifyingSessions) {
72             childVerifyingSession.handleReturnCode();
73         }
74         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
75     }
76 
trySendVerificationCompleteNotification(VerifyingSession child)77     public void trySendVerificationCompleteNotification(VerifyingSession child) {
78         mVerificationState.add(child);
79         if (mVerificationState.size() != mChildVerifyingSessions.size()) {
80             return;
81         }
82         int completeStatus = PackageManager.INSTALL_SUCCEEDED;
83         String errorMsg = null;
84         for (VerifyingSession childVerifyingSession : mVerificationState) {
85             int status = childVerifyingSession.getRet();
86             if (status != PackageManager.INSTALL_SUCCEEDED) {
87                 completeStatus = status;
88                 errorMsg = childVerifyingSession.getErrorMessage();
89                 break;
90             }
91         }
92         try {
93             mObserver.onPackageInstalled(null, completeStatus,
94                     errorMsg, new Bundle());
95         } catch (RemoteException e) {
96             Slog.i(TAG, "Observer no longer exists.");
97         }
98     }
99 
100     @Override
toString()101     public String toString() {
102         return "MultiPackageVerifyingSession{" + Integer.toHexString(System.identityHashCode(this))
103                 + "}";
104     }
105 }
106