1 /* 2 * Copyright (C) 2017 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.backup.utils; 18 19 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS; 20 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME; 21 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE; 22 import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT; 23 import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS; 24 25 import static com.android.server.backup.BackupManagerService.TAG; 26 27 import android.annotation.Nullable; 28 import android.app.IBackupAgent; 29 import android.app.backup.BackupAnnotations.OperationType; 30 import android.app.backup.BackupManagerMonitor; 31 import android.app.backup.BackupRestoreEventLogger.DataTypeResult; 32 import android.app.backup.IBackupManagerMonitor; 33 import android.content.pm.PackageInfo; 34 import android.os.Bundle; 35 import android.os.RemoteException; 36 import android.util.Slog; 37 38 import com.android.internal.annotations.VisibleForTesting; 39 import com.android.internal.infra.AndroidFuture; 40 41 import java.util.List; 42 import java.util.concurrent.TimeUnit; 43 import java.util.concurrent.TimeoutException; 44 45 /** 46 * Utility methods to log BackupManagerMonitor events. 47 */ 48 public class BackupManagerMonitorEventSender { 49 /** 50 * Timeout for how long we wait before we give up on getting logs from a {@link IBackupAgent}. 51 * We expect this to be very fast since the agent immediately returns whatever logs have been 52 * accumulated. The timeout adds a bit more security and ensures we don't hang the B&R waiting 53 * for non-essential logs. 54 */ 55 private static final int AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS = 500; 56 @Nullable private IBackupManagerMonitor mMonitor; 57 private final BackupManagerMonitorDumpsysUtils mBackupManagerMonitorDumpsysUtils; BackupManagerMonitorEventSender(@ullable IBackupManagerMonitor monitor)58 public BackupManagerMonitorEventSender(@Nullable IBackupManagerMonitor monitor) { 59 mMonitor = monitor; 60 mBackupManagerMonitorDumpsysUtils = new BackupManagerMonitorDumpsysUtils(); 61 } 62 63 @VisibleForTesting BackupManagerMonitorEventSender(@ullable IBackupManagerMonitor monitor, BackupManagerMonitorDumpsysUtils backupManagerMonitorDumpsysUtils)64 BackupManagerMonitorEventSender(@Nullable IBackupManagerMonitor monitor, 65 BackupManagerMonitorDumpsysUtils backupManagerMonitorDumpsysUtils) { 66 mMonitor = monitor; 67 mBackupManagerMonitorDumpsysUtils = backupManagerMonitorDumpsysUtils; 68 } 69 setMonitor(IBackupManagerMonitor monitor)70 public void setMonitor(IBackupManagerMonitor monitor) { 71 mMonitor = monitor; 72 } 73 74 @Nullable getMonitor()75 public IBackupManagerMonitor getMonitor() { 76 return mMonitor; 77 } 78 79 /** 80 * Notifies monitor about the event. 81 * 82 * Calls {@link IBackupManagerMonitor#onEvent(Bundle)} with a bundle representing current event. 83 * 84 * @param id - event id. 85 * @param pkg - package event is related to. 86 * @param category - event category. 87 * @param extras - additional event data. 88 */ monitorEvent( int id, @Nullable PackageInfo pkg, int category, @Nullable Bundle extras)89 public void monitorEvent( 90 int id, 91 @Nullable PackageInfo pkg, 92 int category, 93 @Nullable Bundle extras) { 94 try { 95 Bundle bundle = new Bundle(); 96 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id); 97 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category); 98 if (pkg != null) { 99 bundle.putString(EXTRA_LOG_EVENT_PACKAGE_NAME, 100 pkg.packageName); 101 bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION, 102 pkg.versionCode); 103 bundle.putLong(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION, 104 pkg.getLongVersionCode()); 105 } 106 if (extras != null) { 107 bundle.putAll(extras); 108 if (extras.containsKey(EXTRA_LOG_OPERATION_TYPE) && 109 extras.getInt(EXTRA_LOG_OPERATION_TYPE) == OperationType.RESTORE){ 110 mBackupManagerMonitorDumpsysUtils 111 .parseBackupManagerMonitorRestoreEventForDumpsys(bundle); 112 } 113 } 114 115 if (mMonitor != null) { 116 mMonitor.onEvent(bundle); 117 } else { 118 Slog.w(TAG, "backup manager monitor is null unable to send event"); 119 } 120 } catch (RemoteException e) { 121 mMonitor = null; 122 Slog.w(TAG, "backup manager monitor went away"); 123 } 124 } 125 126 /** 127 * Extracts logging results from the provided {@code agent} and notifies the {@code monitor} 128 * about them. 129 * 130 * <p>Note that this method does two separate binder calls (one to the agent and one to the 131 * monitor). 132 * 133 * @param pkg - package the {@code agent} belongs to. 134 * @param agent - the {@link IBackupAgent} to retrieve logs from. 135 */ monitorAgentLoggingResults(PackageInfo pkg, IBackupAgent agent)136 public void monitorAgentLoggingResults(PackageInfo pkg, IBackupAgent agent) { 137 if (mMonitor == null) { 138 Slog.i(TAG, "backup manager monitor is null unable to send event"+pkg); 139 } 140 141 try { 142 AndroidFuture<List<DataTypeResult>> resultsFuture = 143 new AndroidFuture<>(); 144 AndroidFuture<Integer> operationTypeFuture = new AndroidFuture<>(); 145 agent.getLoggerResults(resultsFuture); 146 agent.getOperationType(operationTypeFuture); 147 sendAgentLoggingResults(pkg, 148 resultsFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS), 149 operationTypeFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, 150 TimeUnit.MILLISECONDS)); 151 } catch (TimeoutException e) { 152 Slog.w(TAG, "Timeout while waiting to retrieve logging results from agent", e); 153 } catch (Exception e) { 154 Slog.w(TAG, "Failed to retrieve logging results from agent", e); 155 } 156 } 157 sendAgentLoggingResults(PackageInfo pkg, List<DataTypeResult> results, @OperationType int operationType)158 public void sendAgentLoggingResults(PackageInfo pkg, List<DataTypeResult> results, 159 @OperationType int operationType) { 160 Bundle loggerResultsBundle = new Bundle(); 161 loggerResultsBundle.putParcelableList( 162 EXTRA_LOG_AGENT_LOGGING_RESULTS, results); 163 loggerResultsBundle.putInt(EXTRA_LOG_OPERATION_TYPE, operationType); 164 monitorEvent( 165 LOG_EVENT_ID_AGENT_LOGGING_RESULTS, 166 pkg, 167 LOG_EVENT_CATEGORY_AGENT, 168 loggerResultsBundle); 169 } 170 171 /** 172 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 173 * be created. 174 * 175 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 176 * @param key - key. 177 * @param value - value. 178 * @return extras if it was not null and new bundle otherwise. 179 */ putMonitoringExtra(Bundle extras, String key, String value)180 public static Bundle putMonitoringExtra(Bundle extras, String key, String value) { 181 if (extras == null) { 182 extras = new Bundle(); 183 } 184 extras.putString(key, value); 185 return extras; 186 } 187 188 /** 189 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 190 * be created. 191 * 192 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 193 * @param key - key. 194 * @param value - value. 195 * @return extras if it was not null and new bundle otherwise. 196 */ putMonitoringExtra(Bundle extras, String key, long value)197 public static Bundle putMonitoringExtra(Bundle extras, String key, long value) { 198 if (extras == null) { 199 extras = new Bundle(); 200 } 201 extras.putLong(key, value); 202 return extras; 203 } 204 205 /** 206 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 207 * be created. 208 * 209 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 210 * @param key - key. 211 * @param value - value. 212 * @return extras if it was not null and new bundle otherwise. 213 */ putMonitoringExtra(Bundle extras, String key, boolean value)214 public static Bundle putMonitoringExtra(Bundle extras, String key, boolean value) { 215 if (extras == null) { 216 extras = new Bundle(); 217 } 218 extras.putBoolean(key, value); 219 return extras; 220 } 221 222 /** 223 * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will 224 * be created. 225 * 226 * @param extras - bundle where to add key-value to, if null a new bundle will be created. 227 * @param key - key. 228 * @param value - value. 229 * @return extras if it was not null and new bundle otherwise. 230 */ putMonitoringExtra(Bundle extras, String key, int value)231 public static Bundle putMonitoringExtra(Bundle extras, String key, int value) { 232 if (extras == null) { 233 extras = new Bundle(); 234 } 235 extras.putInt(key, value); 236 return extras; 237 } 238 } 239