1 /*
2  * Copyright (C) 2021 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.CHECK_PENDING_INTEGRITY_VERIFICATION;
22 import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
23 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
24 import static com.android.server.pm.PackageManagerService.DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD;
25 import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_INSTALL_OBSERVER;
26 import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_POST_DELETE;
27 import static com.android.server.pm.PackageManagerService.DEFERRED_PENDING_KILL_INSTALL_OBSERVER;
28 import static com.android.server.pm.PackageManagerService.DOMAIN_VERIFICATION;
29 import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_STATUS;
30 import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_TIMEOUT;
31 import static com.android.server.pm.PackageManagerService.INSTANT_APP_RESOLUTION_PHASE_TWO;
32 import static com.android.server.pm.PackageManagerService.INTEGRITY_VERIFICATION_COMPLETE;
33 import static com.android.server.pm.PackageManagerService.PACKAGE_VERIFIED;
34 import static com.android.server.pm.PackageManagerService.POST_INSTALL;
35 import static com.android.server.pm.PackageManagerService.PRUNE_UNUSED_STATIC_SHARED_LIBRARIES;
36 import static com.android.server.pm.PackageManagerService.SEND_PENDING_BROADCAST;
37 import static com.android.server.pm.PackageManagerService.TAG;
38 import static com.android.server.pm.PackageManagerService.WRITE_PACKAGE_LIST;
39 import static com.android.server.pm.PackageManagerService.WRITE_SETTINGS;
40 
41 import android.content.Intent;
42 import android.content.pm.InstantAppRequest;
43 import android.content.pm.PackageManager;
44 import android.content.pm.PackageManagerInternal;
45 import android.net.Uri;
46 import android.os.Handler;
47 import android.os.Looper;
48 import android.os.Message;
49 import android.os.Process;
50 import android.os.Trace;
51 import android.os.UserHandle;
52 import android.provider.Settings;
53 import android.util.Log;
54 import android.util.Slog;
55 
56 import java.io.IOException;
57 
58 /**
59  * Part of PackageManagerService that handles events.
60  */
61 final class PackageHandler extends Handler {
62     private final PackageManagerService mPm;
63 
PackageHandler(Looper looper, PackageManagerService pm)64     PackageHandler(Looper looper, PackageManagerService pm) {
65         super(looper);
66         mPm = pm;
67     }
68 
69     @Override
handleMessage(Message msg)70     public void handleMessage(Message msg) {
71         try {
72             doHandleMessage(msg);
73         } finally {
74             Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
75         }
76     }
77 
doHandleMessage(Message msg)78     void doHandleMessage(Message msg) {
79         switch (msg.what) {
80             case SEND_PENDING_BROADCAST: {
81                 mPm.sendPendingBroadcasts();
82                 break;
83             }
84             case POST_INSTALL: {
85                 if (DEBUG_INSTALL) Log.v(TAG, "Handling post-install for " + msg.arg1);
86 
87                 InstallRequest request = mPm.mRunningInstalls.get(msg.arg1);
88                 final boolean didRestore = (msg.arg2 != 0);
89                 mPm.mRunningInstalls.delete(msg.arg1);
90 
91                 if (request == null) {
92                     if (DEBUG_INSTALL) {
93                         Slog.i(TAG, "InstallRequest is null. Nothing to do for post-install "
94                                 + "token " + msg.arg1);
95                     }
96                     break;
97                 }
98                 request.closeFreezer();
99                 request.onInstallCompleted();
100                 request.runPostInstallRunnable();
101                 if (!request.isInstallExistingForUser()) {
102                     mPm.handlePackagePostInstall(request, didRestore);
103                 } else if (DEBUG_INSTALL) {
104                     // No post-install when we run restore from installExistingPackageForUser
105                     Slog.i(TAG, "Nothing to do for post-install token " + msg.arg1);
106                 }
107 
108                 Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1);
109             } break;
110             case DEFERRED_NO_KILL_POST_DELETE: {
111                 CleanUpArgs args = (CleanUpArgs) msg.obj;
112                 if (args != null) {
113                     mPm.cleanUpResources(args.getPackageName(), args.getCodeFile(),
114                             args.getInstructionSets());
115                 }
116             } break;
117             case DEFERRED_NO_KILL_INSTALL_OBSERVER:
118             case DEFERRED_PENDING_KILL_INSTALL_OBSERVER: {
119                 final String packageName = (String) msg.obj;
120                 if (packageName != null) {
121                     final boolean killApp = msg.what == DEFERRED_PENDING_KILL_INSTALL_OBSERVER;
122                     mPm.notifyInstallObserver(packageName, killApp);
123                 }
124             } break;
125             case WRITE_SETTINGS: {
126                 mPm.writeSettings(/*sync=*/false);
127             } break;
128             case WRITE_PACKAGE_LIST: {
129                 mPm.writePackageList(msg.arg1);
130             } break;
131             case CHECK_PENDING_VERIFICATION: {
132                 final int verificationId = msg.arg1;
133                 final boolean streaming = msg.arg2 != 0;
134                 final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
135 
136                 if (state == null || state.isVerificationComplete()) {
137                     // Not found or complete.
138                     break;
139                 }
140 
141                 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
142                 if (!streaming && state.timeoutExtended(response.callerUid)) {
143                     // Timeout extended.
144                     break;
145                 }
146 
147                 VerificationUtils.processVerificationResponseOnTimeout(verificationId, state,
148                         response, mPm);
149 
150                 break;
151             }
152             case CHECK_PENDING_INTEGRITY_VERIFICATION: {
153                 final int verificationId = msg.arg1;
154                 final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
155 
156                 if (state != null && !state.isIntegrityVerificationComplete()) {
157                     final VerifyingSession verifyingSession = state.getVerifyingSession();
158                     final Uri originUri = Uri.fromFile(verifyingSession.mOriginInfo.mResolvedFile);
159 
160                     String errorMsg = "Integrity verification timed out for " + originUri;
161                     Slog.i(TAG, errorMsg);
162 
163                     state.setIntegrityVerificationResult(
164                             getDefaultIntegrityVerificationResponse());
165 
166                     if (getDefaultIntegrityVerificationResponse()
167                             == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
168                         Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
169                     } else {
170                         verifyingSession.setReturnCode(
171                                 PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
172                                 errorMsg);
173                     }
174 
175                     if (state.areAllVerificationsComplete()) {
176                         mPm.mPendingVerification.remove(verificationId);
177                     }
178 
179                     Trace.asyncTraceEnd(
180                             TRACE_TAG_PACKAGE_MANAGER,
181                             "integrity_verification",
182                             verificationId);
183 
184                     verifyingSession.handleIntegrityVerificationFinished();
185                 }
186                 break;
187             }
188             case PACKAGE_VERIFIED: {
189                 final int verificationId = msg.arg1;
190 
191                 final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
192                 if (state == null) {
193                     Slog.w(TAG, "Verification with id " + verificationId
194                             + " not found."
195                             + " It may be invalid or overridden by integrity verification");
196                     break;
197                 }
198                 if (state.isVerificationComplete()) {
199                     Slog.w(TAG, "Verification with id " + verificationId + " already complete.");
200                     break;
201                 }
202 
203                 final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
204                 VerificationUtils.processVerificationResponse(verificationId, state, response, mPm);
205 
206                 break;
207             }
208             case INTEGRITY_VERIFICATION_COMPLETE: {
209                 final int verificationId = msg.arg1;
210 
211                 final PackageVerificationState state = mPm.mPendingVerification.get(verificationId);
212                 if (state == null) {
213                     Slog.w(TAG, "Integrity verification with id " + verificationId
214                             + " not found. It may be invalid or overridden by verifier");
215                     break;
216                 }
217 
218                 final int response = (Integer) msg.obj;
219                 final VerifyingSession verifyingSession = state.getVerifyingSession();
220                 final Uri originUri = Uri.fromFile(verifyingSession.mOriginInfo.mResolvedFile);
221 
222                 state.setIntegrityVerificationResult(response);
223 
224                 if (response == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
225                     Slog.i(TAG, "Integrity check passed for " + originUri);
226                 } else {
227                     verifyingSession.setReturnCode(
228                             PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
229                             "Integrity check failed for " + originUri);
230                 }
231 
232                 if (state.areAllVerificationsComplete()) {
233                     mPm.mPendingVerification.remove(verificationId);
234                 }
235 
236                 Trace.asyncTraceEnd(
237                         TRACE_TAG_PACKAGE_MANAGER,
238                         "integrity_verification",
239                         verificationId);
240 
241                 verifyingSession.handleIntegrityVerificationFinished();
242                 break;
243             }
244             case INSTANT_APP_RESOLUTION_PHASE_TWO: {
245                 InstantAppResolver.doInstantAppResolutionPhaseTwo(mPm.mContext,
246                         mPm.snapshotComputer(),
247                         mPm.mUserManager,
248                         mPm.mInstantAppResolverConnection,
249                         (InstantAppRequest) msg.obj,
250                         mPm.mInstantAppInstallerActivity,
251                         mPm.mHandler);
252                 break;
253             }
254             case ENABLE_ROLLBACK_STATUS: {
255                 final int enableRollbackToken = msg.arg1;
256                 final int enableRollbackCode = msg.arg2;
257                 final VerifyingSession params =
258                         mPm.mPendingEnableRollback.get(enableRollbackToken);
259                 if (params == null) {
260                     Slog.w(TAG, "Invalid rollback enabled token "
261                             + enableRollbackToken + " received");
262                     break;
263                 }
264 
265                 mPm.mPendingEnableRollback.remove(enableRollbackToken);
266 
267                 if (enableRollbackCode != PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED) {
268                     final Uri originUri = Uri.fromFile(params.mOriginInfo.mResolvedFile);
269                     Slog.w(TAG, "Failed to enable rollback for " + originUri);
270                     Slog.w(TAG, "Continuing with installation of " + originUri);
271                 }
272 
273                 Trace.asyncTraceEnd(
274                         TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
275 
276                 params.handleRollbackEnabled();
277                 break;
278             }
279             case ENABLE_ROLLBACK_TIMEOUT: {
280                 final int enableRollbackToken = msg.arg1;
281                 final int sessionId = msg.arg2;
282                 final VerifyingSession params =
283                         mPm.mPendingEnableRollback.get(enableRollbackToken);
284                 if (params != null) {
285                     final Uri originUri = Uri.fromFile(params.mOriginInfo.mResolvedFile);
286 
287                     Slog.w(TAG, "Enable rollback timed out for " + originUri);
288                     mPm.mPendingEnableRollback.remove(enableRollbackToken);
289 
290                     Slog.w(TAG, "Continuing with installation of " + originUri);
291                     Trace.asyncTraceEnd(
292                             TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
293                     params.handleRollbackEnabled();
294                     Intent rollbackTimeoutIntent = new Intent(
295                             Intent.ACTION_CANCEL_ENABLE_ROLLBACK);
296                     rollbackTimeoutIntent.putExtra(
297                             PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
298                             sessionId);
299                     rollbackTimeoutIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
300                             | Intent.FLAG_RECEIVER_FOREGROUND);
301                     mPm.mContext.sendBroadcastAsUser(rollbackTimeoutIntent, UserHandle.SYSTEM,
302                             android.Manifest.permission.PACKAGE_ROLLBACK_AGENT);
303                 }
304                 break;
305             }
306             case DOMAIN_VERIFICATION: {
307                 int messageCode = msg.arg1;
308                 Object object = msg.obj;
309                 mPm.mDomainVerificationManager.runMessage(messageCode, object);
310                 break;
311             }
312             case PRUNE_UNUSED_STATIC_SHARED_LIBRARIES: {
313                 try {
314                     mPm.mInjector.getSharedLibrariesImpl().pruneUnusedStaticSharedLibraries(
315                             mPm.snapshotComputer(),
316                             Long.MAX_VALUE,
317                             Settings.Global.getLong(mPm.mContext.getContentResolver(),
318                                     Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
319                                     DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD));
320                 } catch (IOException e) {
321                     Log.w(TAG, "Failed to prune unused static shared libraries :"
322                             + e.getMessage());
323                 }
324                 break;
325             }
326         }
327     }
328 
329     /**
330      * Get the default integrity verification response code.
331      */
getDefaultIntegrityVerificationResponse()332     private int getDefaultIntegrityVerificationResponse() {
333         // We are not exposing this as a user-configurable setting because we don't want to provide
334         // an easy way to get around the integrity check.
335         return PackageManager.VERIFICATION_REJECT;
336     }
337 }
338