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