blob: a62616623cb5804bab2a5b834978dba54330f755 [file] [log] [blame]
Zimuzoc4073cc2019-01-18 18:39:18 +00001/*
2 * Copyright (C) 2019 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
17package com.android.server.rollback;
18
Gavin Corkerydd1daba2019-11-27 19:11:13 +000019import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
20import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
21import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
22import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
23import static android.util.StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
24
25import android.annotation.NonNull;
Zimuzoda972362019-04-27 19:57:58 +010026import android.annotation.Nullable;
Zimuzoff991762019-02-01 19:25:44 +000027import android.content.BroadcastReceiver;
Zimuzoc4073cc2019-01-18 18:39:18 +000028import android.content.Context;
29import android.content.Intent;
Zimuzoff991762019-02-01 19:25:44 +000030import android.content.IntentFilter;
31import android.content.pm.PackageInstaller;
Zimuzo03eeb132019-01-30 15:13:56 +000032import android.content.pm.PackageManager;
Zimuzoc1197802019-01-30 12:05:41 +000033import android.content.pm.VersionedPackage;
Richard Uhler0e961922019-01-25 13:07:08 +000034import android.content.rollback.PackageRollbackInfo;
Zimuzoc4073cc2019-01-18 18:39:18 +000035import android.content.rollback.RollbackInfo;
36import android.content.rollback.RollbackManager;
Zimuzo841c4942019-03-04 12:31:48 +000037import android.os.Environment;
38import android.os.FileUtils;
Zimuzoc4073cc2019-01-18 18:39:18 +000039import android.os.Handler;
40import android.os.HandlerThread;
Zimuzoff991762019-02-01 19:25:44 +000041import android.os.PowerManager;
shafikc5805fb92019-04-29 20:08:07 +010042import android.os.SystemProperties;
Zimuzo03eeb132019-01-30 15:13:56 +000043import android.text.TextUtils;
Zimuzo8d231b42019-05-16 18:09:23 +010044import android.util.ArraySet;
Zimuzo03eeb132019-01-30 15:13:56 +000045import android.util.Slog;
46import android.util.StatsLog;
Zimuzoc4073cc2019-01-18 18:39:18 +000047
Zimuzo03eeb132019-01-30 15:13:56 +000048import com.android.internal.R;
Zimuzo8d231b42019-05-16 18:09:23 +010049import com.android.internal.annotations.GuardedBy;
Zimuzoc4073cc2019-01-18 18:39:18 +000050import com.android.server.PackageWatchdog;
Gavin Corkeryf305f4d2019-11-27 15:46:29 +000051import com.android.server.PackageWatchdog.FailureReasons;
Zimuzoc4073cc2019-01-18 18:39:18 +000052import com.android.server.PackageWatchdog.PackageHealthObserver;
Zimuzoe5009cd2019-01-23 18:11:58 +000053import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
Zimuzoc4073cc2019-01-18 18:39:18 +000054
Zimuzo841c4942019-03-04 12:31:48 +000055import libcore.io.IoUtils;
56
57import java.io.File;
58import java.io.FileOutputStream;
59import java.io.IOException;
60import java.io.PrintWriter;
Richard Uhlerbf5b5c42019-01-28 15:26:37 +000061import java.util.Collections;
Zimuzoc4073cc2019-01-18 18:39:18 +000062import java.util.List;
Zimuzo8d231b42019-05-16 18:09:23 +010063import java.util.Set;
shafikc5805fb92019-04-29 20:08:07 +010064import java.util.concurrent.TimeUnit;
Zimuzoc4073cc2019-01-18 18:39:18 +000065
66/**
shafikc5805fb92019-04-29 20:08:07 +010067 * {@link PackageHealthObserver} for {@link RollbackManagerService}.
68 * This class monitors crashes and triggers RollbackManager rollback accordingly.
69 * It also monitors native crashes for some short while after boot.
Zimuzoc4073cc2019-01-18 18:39:18 +000070 *
71 * @hide
72 */
73public final class RollbackPackageHealthObserver implements PackageHealthObserver {
74 private static final String TAG = "RollbackPackageHealthObserver";
75 private static final String NAME = "rollback-observer";
Zimuzo841c4942019-03-04 12:31:48 +000076 private static final int INVALID_ROLLBACK_ID = -1;
shafikc5805fb92019-04-29 20:08:07 +010077 // TODO: make the following values configurable via DeviceConfig
78 private static final long NATIVE_CRASH_POLLING_INTERVAL_MILLIS =
79 TimeUnit.SECONDS.toMillis(30);
80 private static final long NUMBER_OF_NATIVE_CRASH_POLLS = 10;
81
Zimuzo841c4942019-03-04 12:31:48 +000082 private final Context mContext;
83 private final Handler mHandler;
84 private final File mLastStagedRollbackIdFile;
Zimuzo8d231b42019-05-16 18:09:23 +010085 // Staged rollback ids that have been committed but their session is not yet ready
86 @GuardedBy("mPendingStagedRollbackIds")
87 private final Set<Integer> mPendingStagedRollbackIds = new ArraySet<>();
shafikc5805fb92019-04-29 20:08:07 +010088 // this field is initialized in the c'tor and then only accessed from mHandler thread, so
89 // no need to guard with a lock
90 private long mNumberOfNativeCrashPollsRemaining;
Zimuzoc4073cc2019-01-18 18:39:18 +000091
92 RollbackPackageHealthObserver(Context context) {
93 mContext = context;
shafikc5805fb92019-04-29 20:08:07 +010094 mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
Zimuzoc4073cc2019-01-18 18:39:18 +000095 HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
96 handlerThread.start();
97 mHandler = handlerThread.getThreadHandler();
Zimuzo841c4942019-03-04 12:31:48 +000098 File dataDir = new File(Environment.getDataDirectory(), "rollback-observer");
99 dataDir.mkdirs();
100 mLastStagedRollbackIdFile = new File(dataDir, "last-staged-rollback-id");
Zimuzoc4073cc2019-01-18 18:39:18 +0000101 PackageWatchdog.getInstance(mContext).registerHealthObserver(this);
102 }
103
104 @Override
Zimuzo71d931e2019-02-01 13:08:16 +0000105 public int onHealthCheckFailed(VersionedPackage failedPackage) {
Zimuzoda972362019-04-27 19:57:58 +0100106 if (getAvailableRollback(mContext.getSystemService(RollbackManager.class), failedPackage)
107 == null) {
Zimuzoe5009cd2019-01-23 18:11:58 +0000108 // Don't handle the notification, no rollbacks available for the package
109 return PackageHealthObserverImpact.USER_IMPACT_NONE;
Zimuzoda972362019-04-27 19:57:58 +0100110 } else {
111 // Rollback is available, we may get a callback into #execute
112 return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
Zimuzoc4073cc2019-01-18 18:39:18 +0000113 }
Zimuzoe5009cd2019-01-23 18:11:58 +0000114 }
115
116 @Override
Gavin Corkeryf305f4d2019-11-27 15:46:29 +0000117 public boolean execute(VersionedPackage failedPackage, @FailureReasons int rollbackReason) {
Zimuzo03eeb132019-01-30 15:13:56 +0000118 RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
Zimuzoda972362019-04-27 19:57:58 +0100119 VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
120 RollbackInfo rollback = getAvailableRollback(rollbackManager, failedPackage);
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000121 int reasonToLog = mapFailureReasonToMetric(rollbackReason);
Zimuzoda972362019-04-27 19:57:58 +0100122
123 if (rollback == null) {
Zimuzo9e57ecb2019-02-04 15:34:08 +0000124 Slog.w(TAG, "Expected rollback but no valid rollback found for package: [ "
Zimuzo71d931e2019-02-01 13:08:16 +0000125 + failedPackage.getPackageName() + "] with versionCode: ["
126 + failedPackage.getVersionCode() + "]");
Zimuzo03eeb132019-01-30 15:13:56 +0000127 return false;
128 }
Zimuzoff991762019-02-01 19:25:44 +0000129
Zimuzoda972362019-04-27 19:57:58 +0100130 logEvent(moduleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000131 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE,
132 reasonToLog, failedPackage.getPackageName());
Zimuzoe5009cd2019-01-23 18:11:58 +0000133 LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
Zimuzoda972362019-04-27 19:57:58 +0100134 int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
135 RollbackManager.STATUS_FAILURE);
136 if (status == RollbackManager.STATUS_SUCCESS) {
137 if (rollback.isStaged()) {
138 int rollbackId = rollback.getRollbackId();
Zimuzo8d231b42019-05-16 18:09:23 +0100139 synchronized (mPendingStagedRollbackIds) {
140 mPendingStagedRollbackIds.add(rollbackId);
141 }
Zimuzoda972362019-04-27 19:57:58 +0100142 BroadcastReceiver listener =
143 listenForStagedSessionReady(rollbackManager, rollbackId,
144 moduleMetadataPackage);
145 handleStagedSessionChange(rollbackManager, rollbackId, listener,
146 moduleMetadataPackage);
Zimuzo9e57ecb2019-02-04 15:34:08 +0000147 } else {
Zimuzoda972362019-04-27 19:57:58 +0100148 logEvent(moduleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000149 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
150 reasonToLog, failedPackage.getPackageName());
Zimuzo9e57ecb2019-02-04 15:34:08 +0000151 }
Zimuzoda972362019-04-27 19:57:58 +0100152 } else {
153 logEvent(moduleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000154 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
155 reasonToLog, failedPackage.getPackageName());
Zimuzoe5009cd2019-01-23 18:11:58 +0000156 }
157 });
158
Zimuzoe5009cd2019-01-23 18:11:58 +0000159 mHandler.post(() ->
Zimuzoc1197802019-01-30 12:05:41 +0000160 rollbackManager.commitRollback(rollback.getRollbackId(),
Zimuzo9e57ecb2019-02-04 15:34:08 +0000161 Collections.singletonList(failedPackage),
Richard Uhlere87368e2019-01-24 16:34:14 +0000162 rollbackReceiver.getIntentSender()));
Zimuzoe5009cd2019-01-23 18:11:58 +0000163 // Assume rollback executed successfully
164 return true;
165 }
166
167 @Override
168 public String getName() {
169 return NAME;
Zimuzoc4073cc2019-01-18 18:39:18 +0000170 }
171
172 /**
173 * Start observing health of {@code packages} for {@code durationMs}.
174 * This may cause {@code packages} to be rolled back if they crash too freqeuntly.
175 */
176 public void startObservingHealth(List<String> packages, long durationMs) {
Zimuzocaa435e2019-03-20 11:16:06 +0000177 PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
Zimuzoc4073cc2019-01-18 18:39:18 +0000178 }
179
shafikc5805fb92019-04-29 20:08:07 +0100180 /** Verifies the rollback state after a reboot and schedules polling for sometime after reboot
181 * to check for native crashes and mitigate them if needed.
182 */
183 public void onBootCompletedAsync() {
184 mHandler.post(()->onBootCompleted());
185 }
186
187 private void onBootCompleted() {
188 RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
189 PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
190 String moduleMetadataPackageName = getModuleMetadataPackageName();
191 VersionedPackage newModuleMetadataPackage = getModuleMetadataPackage();
192
193 if (getAvailableRollback(rollbackManager, newModuleMetadataPackage) != null) {
194 scheduleCheckAndMitigateNativeCrashes();
195 }
196
Zimuzo841c4942019-03-04 12:31:48 +0000197 int rollbackId = popLastStagedRollbackId();
198 if (rollbackId == INVALID_ROLLBACK_ID) {
199 // No staged rollback before reboot
200 return;
201 }
202
Zimuzo841c4942019-03-04 12:31:48 +0000203 RollbackInfo rollback = null;
204 for (RollbackInfo info : rollbackManager.getRecentlyCommittedRollbacks()) {
205 if (rollbackId == info.getRollbackId()) {
206 rollback = info;
207 break;
208 }
209 }
210
211 if (rollback == null) {
212 Slog.e(TAG, "rollback info not found for last staged rollback: " + rollbackId);
213 return;
214 }
215
Zimuzo841c4942019-03-04 12:31:48 +0000216 // Use the version of the metadata package that was installed before
217 // we rolled back for logging purposes.
shafikc5805fb92019-04-29 20:08:07 +0100218 VersionedPackage oldModuleMetadataPackage = null;
Zimuzo841c4942019-03-04 12:31:48 +0000219 for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
Zimuzoda972362019-04-27 19:57:58 +0100220 if (packageRollback.getPackageName().equals(moduleMetadataPackageName)) {
shafikc5805fb92019-04-29 20:08:07 +0100221 oldModuleMetadataPackage = packageRollback.getVersionRolledBackFrom();
Zimuzo841c4942019-03-04 12:31:48 +0000222 break;
223 }
224 }
225
Zimuzo841c4942019-03-04 12:31:48 +0000226 int sessionId = rollback.getCommittedSessionId();
227 PackageInstaller.SessionInfo sessionInfo = packageInstaller.getSessionInfo(sessionId);
228 if (sessionInfo == null) {
229 Slog.e(TAG, "On boot completed, could not load session id " + sessionId);
230 return;
231 }
232 if (sessionInfo.isStagedSessionApplied()) {
shafikc5805fb92019-04-29 20:08:07 +0100233 logEvent(oldModuleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000234 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS,
235 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
Zimuzo841c4942019-03-04 12:31:48 +0000236 } else if (sessionInfo.isStagedSessionReady()) {
237 // TODO: What do for staged session ready but not applied
238 } else {
shafikc5805fb92019-04-29 20:08:07 +0100239 logEvent(oldModuleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000240 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
241 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN, "");
Zimuzo841c4942019-03-04 12:31:48 +0000242 }
243 }
244
Zimuzoda972362019-04-27 19:57:58 +0100245 private RollbackInfo getAvailableRollback(RollbackManager rollbackManager,
246 VersionedPackage failedPackage) {
Zimuzoc1197802019-01-30 12:05:41 +0000247 for (RollbackInfo rollback : rollbackManager.getAvailableRollbacks()) {
Zimuzoe5009cd2019-01-23 18:11:58 +0000248 for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
Zimuzoda972362019-04-27 19:57:58 +0100249 boolean hasFailedPackage = packageRollback.getPackageName().equals(
Zimuzo71d931e2019-02-01 13:08:16 +0000250 failedPackage.getPackageName())
Zimuzo972e1cd2019-01-28 16:30:01 +0000251 && packageRollback.getVersionRolledBackFrom().getVersionCode()
Zimuzo71d931e2019-02-01 13:08:16 +0000252 == failedPackage.getVersionCode();
Zimuzoda972362019-04-27 19:57:58 +0100253 if (hasFailedPackage) {
254 return rollback;
255 }
Zimuzoe5009cd2019-01-23 18:11:58 +0000256 }
257 }
258 return null;
Zimuzoc4073cc2019-01-18 18:39:18 +0000259 }
Zimuzo03eeb132019-01-30 15:13:56 +0000260
Zimuzoda972362019-04-27 19:57:58 +0100261 @Nullable
Zimuzo841c4942019-03-04 12:31:48 +0000262 private String getModuleMetadataPackageName() {
Zimuzo03eeb132019-01-30 15:13:56 +0000263 String packageName = mContext.getResources().getString(
264 R.string.config_defaultModuleMetadataProvider);
Zimuzo9e57ecb2019-02-04 15:34:08 +0000265 if (TextUtils.isEmpty(packageName)) {
Zimuzo03eeb132019-01-30 15:13:56 +0000266 return null;
267 }
Zimuzo841c4942019-03-04 12:31:48 +0000268 return packageName;
269 }
270
Zimuzoda972362019-04-27 19:57:58 +0100271 @Nullable
Zimuzo841c4942019-03-04 12:31:48 +0000272 private VersionedPackage getModuleMetadataPackage() {
273 String packageName = getModuleMetadataPackageName();
274 if (packageName == null) {
275 return null;
276 }
Zimuzo03eeb132019-01-30 15:13:56 +0000277
278 try {
279 return new VersionedPackage(packageName, mContext.getPackageManager().getPackageInfo(
280 packageName, 0 /* flags */).getLongVersionCode());
281 } catch (PackageManager.NameNotFoundException e) {
282 Slog.w(TAG, "Module metadata provider not found");
283 return null;
284 }
285 }
Zimuzoff991762019-02-01 19:25:44 +0000286
287 private BroadcastReceiver listenForStagedSessionReady(RollbackManager rollbackManager,
Zimuzo841c4942019-03-04 12:31:48 +0000288 int rollbackId, VersionedPackage moduleMetadataPackage) {
Zimuzoff991762019-02-01 19:25:44 +0000289 BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() {
290 @Override
291 public void onReceive(Context context, Intent intent) {
292 handleStagedSessionChange(rollbackManager,
Zimuzo841c4942019-03-04 12:31:48 +0000293 rollbackId, this /* BroadcastReceiver */, moduleMetadataPackage);
Zimuzoff991762019-02-01 19:25:44 +0000294 }
295 };
296 IntentFilter sessionUpdatedFilter =
297 new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED);
298 mContext.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter);
299 return sessionUpdatedReceiver;
300 }
301
302 private void handleStagedSessionChange(RollbackManager rollbackManager, int rollbackId,
Zimuzo841c4942019-03-04 12:31:48 +0000303 BroadcastReceiver listener, VersionedPackage moduleMetadataPackage) {
Zimuzoff991762019-02-01 19:25:44 +0000304 PackageInstaller packageInstaller =
305 mContext.getPackageManager().getPackageInstaller();
306 List<RollbackInfo> recentRollbacks =
307 rollbackManager.getRecentlyCommittedRollbacks();
308 for (int i = 0; i < recentRollbacks.size(); i++) {
309 RollbackInfo recentRollback = recentRollbacks.get(i);
310 int sessionId = recentRollback.getCommittedSessionId();
311 if ((rollbackId == recentRollback.getRollbackId())
312 && (sessionId != PackageInstaller.SessionInfo.INVALID_ID)) {
313 PackageInstaller.SessionInfo sessionInfo =
314 packageInstaller.getSessionInfo(sessionId);
Zimuzo8d231b42019-05-16 18:09:23 +0100315 if (sessionInfo.isStagedSessionReady() && markStagedSessionHandled(rollbackId)) {
Zimuzoff991762019-02-01 19:25:44 +0000316 mContext.unregisterReceiver(listener);
Zimuzo841c4942019-03-04 12:31:48 +0000317 saveLastStagedRollbackId(rollbackId);
Zimuzoda972362019-04-27 19:57:58 +0100318 logEvent(moduleMetadataPackage,
Zimuzo841c4942019-03-04 12:31:48 +0000319 StatsLog
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000320 .WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_BOOT_TRIGGERED,
321 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
322 "");
Zimuzoff991762019-02-01 19:25:44 +0000323 mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
Zimuzo8d231b42019-05-16 18:09:23 +0100324 } else if (sessionInfo.isStagedSessionFailed()
325 && markStagedSessionHandled(rollbackId)) {
Zimuzoda972362019-04-27 19:57:58 +0100326 logEvent(moduleMetadataPackage,
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000327 StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE,
328 WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN,
329 "");
Zimuzoff991762019-02-01 19:25:44 +0000330 mContext.unregisterReceiver(listener);
331 }
332 }
333 }
334 }
Zimuzo841c4942019-03-04 12:31:48 +0000335
Zimuzo8d231b42019-05-16 18:09:23 +0100336 /**
337 * Returns {@code true} if staged session associated with {@code rollbackId} was marked
338 * as handled, {@code false} if already handled.
339 */
340 private boolean markStagedSessionHandled(int rollbackId) {
341 synchronized (mPendingStagedRollbackIds) {
342 return mPendingStagedRollbackIds.remove(rollbackId);
343 }
344 }
345
Zimuzo841c4942019-03-04 12:31:48 +0000346 private void saveLastStagedRollbackId(int stagedRollbackId) {
347 try {
348 FileOutputStream fos = new FileOutputStream(mLastStagedRollbackIdFile);
349 PrintWriter pw = new PrintWriter(fos);
350 pw.println(stagedRollbackId);
351 pw.flush();
352 FileUtils.sync(fos);
353 pw.close();
354 } catch (IOException e) {
355 Slog.e(TAG, "Failed to save last staged rollback id", e);
356 mLastStagedRollbackIdFile.delete();
357 }
358 }
359
360 private int popLastStagedRollbackId() {
361 int rollbackId = INVALID_ROLLBACK_ID;
362 if (!mLastStagedRollbackIdFile.exists()) {
363 return rollbackId;
364 }
365
366 try {
367 rollbackId = Integer.parseInt(
368 IoUtils.readFileAsString(mLastStagedRollbackIdFile.getAbsolutePath()).trim());
369 } catch (IOException | NumberFormatException e) {
370 Slog.e(TAG, "Failed to retrieve last staged rollback id", e);
371 }
372 mLastStagedRollbackIdFile.delete();
373 return rollbackId;
374 }
Zimuzoda972362019-04-27 19:57:58 +0100375
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000376 private static void logEvent(@Nullable VersionedPackage moduleMetadataPackage, int type,
377 int rollbackReason, @NonNull String failingPackageName) {
Zimuzoda972362019-04-27 19:57:58 +0100378 Slog.i(TAG, "Watchdog event occurred of type: " + type);
379 if (moduleMetadataPackage != null) {
Tej Singh73f8e9b2019-05-19 16:52:38 -0700380 StatsLog.logWatchdogRollbackOccurred(type, moduleMetadataPackage.getPackageName(),
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000381 moduleMetadataPackage.getVersionCode(), rollbackReason, failingPackageName);
Zimuzoda972362019-04-27 19:57:58 +0100382 }
383 }
shafikc5805fb92019-04-29 20:08:07 +0100384
385 /**
386 * This method should be only called on mHandler thread, since it modifies
387 * {@link #mNumberOfNativeCrashPollsRemaining} and we want to keep this class lock free.
388 */
389 private void checkAndMitigateNativeCrashes() {
390 mNumberOfNativeCrashPollsRemaining--;
391 // Check if native watchdog reported a crash
Nikita Ioffe76a05792019-10-04 16:51:06 +0100392 if ("1".equals(SystemProperties.get("sys.init.updatable_crashing"))) {
Gavin Corkeryf305f4d2019-11-27 15:46:29 +0000393 execute(getModuleMetadataPackage(), PackageWatchdog.FAILURE_REASON_NATIVE_CRASH);
shafikc5805fb92019-04-29 20:08:07 +0100394 // we stop polling after an attempt to execute rollback, regardless of whether the
395 // attempt succeeds or not
396 } else {
397 if (mNumberOfNativeCrashPollsRemaining > 0) {
398 mHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
399 NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
400 }
401 }
402 }
403
404 /**
405 * Since this method can eventually trigger a RollbackManager rollback, it should be called
406 * only once boot has completed {@code onBootCompleted} and not earlier, because the install
407 * session must be entirely completed before we try to rollback.
408 */
409 private void scheduleCheckAndMitigateNativeCrashes() {
410 Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
411 + "and mitigate native crashes");
412 mHandler.post(()->checkAndMitigateNativeCrashes());
413 }
Gavin Corkerydd1daba2019-11-27 19:11:13 +0000414
415 private int mapFailureReasonToMetric(@FailureReasons int failureReason) {
416 switch (failureReason) {
417 case PackageWatchdog.FAILURE_REASON_NATIVE_CRASH:
418 return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_NATIVE_CRASH;
419 case PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK:
420 return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_EXPLICIT_HEALTH_CHECK;
421 case PackageWatchdog.FAILURE_REASON_APP_CRASH:
422 return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_CRASH;
423 case PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING:
424 return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_APP_NOT_RESPONDING;
425 default:
426 return WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_REASON__REASON_UNKNOWN;
427 }
428 }
429
Zimuzoc4073cc2019-01-18 18:39:18 +0000430}