blob: 28801038ebd10c6751623fcb91bc15c16e277eaa [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
19import android.content.Context;
20import android.content.Intent;
21import android.content.pm.PackageInstaller;
Richard Uhler0e961922019-01-25 13:07:08 +000022import android.content.rollback.PackageRollbackInfo;
Zimuzoc4073cc2019-01-18 18:39:18 +000023import android.content.rollback.RollbackInfo;
24import android.content.rollback.RollbackManager;
25import android.os.Handler;
26import android.os.HandlerThread;
27
28import com.android.server.PackageWatchdog;
29import com.android.server.PackageWatchdog.PackageHealthObserver;
Zimuzoe5009cd2019-01-23 18:11:58 +000030import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
Zimuzoc4073cc2019-01-18 18:39:18 +000031
Richard Uhlerbf5b5c42019-01-28 15:26:37 +000032import java.util.Collections;
Zimuzoc4073cc2019-01-18 18:39:18 +000033import java.util.List;
34
35/**
36 * {@code PackageHealthObserver} for {@code RollbackManagerService}.
37 *
38 * @hide
39 */
40public final class RollbackPackageHealthObserver implements PackageHealthObserver {
41 private static final String TAG = "RollbackPackageHealthObserver";
42 private static final String NAME = "rollback-observer";
43 private Context mContext;
Zimuzoe5009cd2019-01-23 18:11:58 +000044 private RollbackManager mRollbackManager;
Zimuzoc4073cc2019-01-18 18:39:18 +000045 private Handler mHandler;
46
47 RollbackPackageHealthObserver(Context context) {
48 mContext = context;
Zimuzoe5009cd2019-01-23 18:11:58 +000049 mRollbackManager = mContext.getSystemService(RollbackManager.class);
Zimuzoc4073cc2019-01-18 18:39:18 +000050 HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
51 handlerThread.start();
52 mHandler = handlerThread.getThreadHandler();
53 PackageWatchdog.getInstance(mContext).registerHealthObserver(this);
54 }
55
56 @Override
Zimuzoe5009cd2019-01-23 18:11:58 +000057 public int onHealthCheckFailed(String packageName) {
58 RollbackInfo rollback = getAvailableRollback(packageName);
59 if (rollback == null) {
60 // Don't handle the notification, no rollbacks available for the package
61 return PackageHealthObserverImpact.USER_IMPACT_NONE;
Zimuzoc4073cc2019-01-18 18:39:18 +000062 }
Zimuzoe5009cd2019-01-23 18:11:58 +000063 // Rollback is available, we may get a callback into #execute
64 return PackageHealthObserverImpact.USER_IMPACT_MEDIUM;
65 }
66
67 @Override
68 public boolean execute(String packageName) {
69 RollbackInfo rollback = getAvailableRollback(packageName);
70 if (rollback == null) {
71 // Expected a rollback to be available, what happened?
72 return false;
73 }
74
75 // TODO(zezeozue): Only rollback if rollback version == failed package version
76 LocalIntentReceiver rollbackReceiver = new LocalIntentReceiver((Intent result) -> {
77 int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
78 PackageInstaller.STATUS_FAILURE);
79 if (status == PackageInstaller.STATUS_SUCCESS) {
80 // TODO(zezeozue); Log success metrics
81 // Rolledback successfully, no action required by other observers
82 } else {
83 // TODO(zezeozue); Log failure metrics
84 // Rollback failed other observers should have a shot
85 }
86 });
87
88 // TODO(zezeozue): Log initiated metrics
Richard Uhlerbf5b5c42019-01-28 15:26:37 +000089 // TODO: Pass the package as a cause package instead of using
90 // Collections.emptyList once the version of the failing package is
91 // easily available.
Zimuzoe5009cd2019-01-23 18:11:58 +000092 mHandler.post(() ->
Richard Uhlere87368e2019-01-24 16:34:14 +000093 mRollbackManager.commitRollback(rollback.getRollbackId(),
Richard Uhlerbf5b5c42019-01-28 15:26:37 +000094 Collections.emptyList(),
Richard Uhlere87368e2019-01-24 16:34:14 +000095 rollbackReceiver.getIntentSender()));
Zimuzoe5009cd2019-01-23 18:11:58 +000096 // Assume rollback executed successfully
97 return true;
98 }
99
100 @Override
101 public String getName() {
102 return NAME;
Zimuzoc4073cc2019-01-18 18:39:18 +0000103 }
104
105 /**
106 * Start observing health of {@code packages} for {@code durationMs}.
107 * This may cause {@code packages} to be rolled back if they crash too freqeuntly.
108 */
109 public void startObservingHealth(List<String> packages, long durationMs) {
110 PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
111 }
112
Zimuzoe5009cd2019-01-23 18:11:58 +0000113 private RollbackInfo getAvailableRollback(String packageName) {
114 for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) {
115 for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
116 if (packageName.equals(packageRollback.getPackageName())) {
117 // TODO(zezeozue): Only rollback if rollback version == failed package version
118 return rollback;
Zimuzoc4073cc2019-01-18 18:39:18 +0000119 }
Zimuzoe5009cd2019-01-23 18:11:58 +0000120 }
121 }
122 return null;
Zimuzoc4073cc2019-01-18 18:39:18 +0000123 }
124}