1 /*
2  * Copyright (C) 2009 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.commands.bmgr;
18 
19 import android.annotation.IntDef;
20 import android.annotation.UserIdInt;
21 import android.app.backup.BackupManager;
22 import android.app.backup.BackupManagerMonitor;
23 import android.app.backup.BackupProgress;
24 import android.app.backup.BackupRestoreEventLogger;
25 import android.app.backup.BackupTransport;
26 import android.app.backup.IBackupManager;
27 import android.app.backup.IBackupManagerMonitor;
28 import android.app.backup.IBackupObserver;
29 import android.app.backup.IRestoreObserver;
30 import android.app.backup.IRestoreSession;
31 import android.app.backup.ISelectBackupTransportCallback;
32 import android.app.backup.RestoreSet;
33 import android.content.ComponentName;
34 import android.content.Context;
35 import android.content.pm.IPackageManager;
36 import android.content.pm.PackageInfo;
37 import android.os.Bundle;
38 import android.os.RemoteException;
39 import android.os.ServiceManager;
40 import android.os.SystemClock;
41 import android.os.UserHandle;
42 import android.util.ArraySet;
43 import android.util.Slog;
44 
45 import com.android.internal.annotations.GuardedBy;
46 import com.android.internal.annotations.VisibleForTesting;
47 
48 import java.lang.annotation.Retention;
49 import java.lang.annotation.RetentionPolicy;
50 import java.util.ArrayList;
51 import java.util.Arrays;
52 import java.util.HashSet;
53 import java.util.List;
54 import java.util.Set;
55 import java.util.concurrent.CountDownLatch;
56 
57 /**
58  * Adb shell command for {@link android.app.backup.IBackupManager}.
59  */
60 public class Bmgr {
61     public static final String TAG = "Bmgr";
62 
63     private final IBackupManager mBmgr;
64     private IRestoreSession mRestore;
65 
66     private static final String BMGR_NOT_RUNNING_ERR =
67             "Error: Could not access the Backup Manager.  Is the system running?";
68     private static final String BMGR_NOT_ACTIVATED_FOR_USER =
69             "Error: Backup Manager is not activated for user ";
70     private static final String BMGR_ERR_NO_RESTORESESSION_FOR_USER =
71             "Error: Could not get restore session for user ";
72     private static final String TRANSPORT_NOT_RUNNING_ERR =
73             "Error: Could not access the backup transport.  Is the system running?";
74     private static final String PM_NOT_RUNNING_ERR =
75             "Error: Could not access the Package Manager.  Is the system running?";
76 
77     private String[] mArgs;
78     private int mNextArg;
79 
80     @VisibleForTesting
Bmgr(IBackupManager bmgr)81     Bmgr(IBackupManager bmgr) {
82         mBmgr = bmgr;
83     }
84 
Bmgr()85     Bmgr() {
86         mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
87     }
88 
main(String[] args)89     public static void main(String[] args) {
90         try {
91             new Bmgr().run(args);
92         } catch (Exception e) {
93             System.err.println("Exception caught:");
94             e.printStackTrace();
95         }
96     }
97 
run(String[] args)98     public void run(String[] args) {
99         if (args.length < 1) {
100             showUsage();
101             return;
102         }
103 
104         mArgs = args;
105         mNextArg = 0;
106         int userId = parseUserId();
107         String op = nextArg();
108         Slog.v(TAG, "Running " + op + " for user:" + userId);
109 
110         if (mBmgr == null) {
111             System.err.println(BMGR_NOT_RUNNING_ERR);
112             return;
113         }
114 
115         if ("activate".equals(op)) {
116             doActivateService(userId);
117             return;
118         }
119 
120         if ("activated".equals(op)) {
121             doActivated(userId);
122             return;
123         }
124 
125         if (!isBackupActive(userId)) {
126             return;
127         }
128 
129         if ("autorestore".equals(op)) {
130             doAutoRestore(userId);
131             return;
132         }
133 
134         if ("enabled".equals(op)) {
135             doEnabled(userId);
136             return;
137         }
138 
139         if ("enable".equals(op)) {
140             doEnable(userId);
141             return;
142         }
143 
144         if ("run".equals(op)) {
145             doRun(userId);
146             return;
147         }
148 
149         if ("backup".equals(op)) {
150             doBackup(userId);
151             return;
152         }
153 
154         if ("init".equals(op)) {
155             doInit(userId);
156             return;
157         }
158 
159         if ("list".equals(op)) {
160             doList(userId);
161             return;
162         }
163 
164         if ("restore".equals(op)) {
165             doRestore(userId);
166             return;
167         }
168 
169         if ("transport".equals(op)) {
170             doTransport(userId);
171             return;
172         }
173 
174         if ("wipe".equals(op)) {
175             doWipe(userId);
176             return;
177         }
178 
179         if ("fullbackup".equals(op)) {
180             doFullTransportBackup(userId);
181             return;
182         }
183 
184         if ("backupnow".equals(op)) {
185             doBackupNow(userId);
186             return;
187         }
188 
189         if ("cancel".equals(op)) {
190             doCancel(userId);
191             return;
192         }
193 
194         if ("whitelist".equals(op)) {
195             doPrintAllowlist();
196             return;
197         }
198 
199         if ("scheduling".equals(op)) {
200             setSchedulingEnabled(userId);
201             return;
202         }
203 
204         System.err.println("Unknown command");
205         showUsage();
206     }
207 
setSchedulingEnabled(int userId)208     private void setSchedulingEnabled(int userId) {
209         String arg = nextArg();
210         if (arg == null) {
211             showUsage();
212             return;
213         }
214 
215         try {
216             boolean enable = Boolean.parseBoolean(arg);
217             mBmgr.setFrameworkSchedulingEnabledForUser(userId, enable);
218             System.out.println(
219                     "Backup scheduling is now "
220                             + (enable ? "enabled" : "disabled")
221                             + " for user "
222                             + userId);
223         } catch (RemoteException e) {
224             handleRemoteException(e);
225         }
226     }
227 
handleRemoteException(RemoteException e)228     private void handleRemoteException(RemoteException e) {
229         System.err.println(e.toString());
230         System.err.println(BMGR_NOT_RUNNING_ERR);
231     }
232 
isBackupActive(@serIdInt int userId)233     private boolean isBackupActive(@UserIdInt int userId) {
234         try {
235             if (!mBmgr.isBackupServiceActive(userId)) {
236                 System.err.println(BMGR_NOT_ACTIVATED_FOR_USER + userId);
237                 return false;
238             }
239         } catch (RemoteException e) {
240             handleRemoteException(e);
241             return false;
242         }
243 
244         return true;
245     }
246 
doAutoRestore(int userId)247     private void doAutoRestore(int userId) {
248         String arg = nextArg();
249         if (arg == null) {
250             showUsage();
251             return;
252         }
253 
254         try {
255             boolean enable = Boolean.parseBoolean(arg);
256             mBmgr.setAutoRestore(enable);
257             System.out.println(
258                     "Auto restore is now "
259                             + (enable ? "enabled" : "disabled")
260                             + " for user "
261                             + userId);
262         } catch (RemoteException e) {
263             handleRemoteException(e);
264         }
265     }
266 
activatedToString(boolean activated)267     private String activatedToString(boolean activated) {
268         return activated ? "activated" : "deactivated";
269     }
270 
doActivated(@serIdInt int userId)271     private void doActivated(@UserIdInt int userId) {
272         try {
273             System.out.println("Backup Manager currently "
274                     + activatedToString(mBmgr.isBackupServiceActive(userId)));
275         } catch (RemoteException e) {
276             handleRemoteException(e);
277         }
278 
279     }
280 
enableToString(boolean enabled)281     private String enableToString(boolean enabled) {
282         return enabled ? "enabled" : "disabled";
283     }
284 
doEnabled(@serIdInt int userId)285     private void doEnabled(@UserIdInt int userId) {
286         try {
287             boolean isEnabled = mBmgr.isBackupEnabledForUser(userId);
288             System.out.println("Backup Manager currently "
289                     + enableToString(isEnabled));
290         } catch (RemoteException e) {
291             handleRemoteException(e);
292         }
293     }
294 
doEnable(@serIdInt int userId)295     private void doEnable(@UserIdInt int userId) {
296         String arg = nextArg();
297         if (arg == null) {
298             showUsage();
299             return;
300         }
301 
302         try {
303             boolean enable = Boolean.parseBoolean(arg);
304             mBmgr.setBackupEnabledForUser(userId, enable);
305             System.out.println("Backup Manager now " + enableToString(enable));
306         } catch (NumberFormatException e) {
307             showUsage();
308             return;
309         } catch (RemoteException e) {
310             handleRemoteException(e);
311         }
312     }
313 
doRun(@serIdInt int userId)314     void doRun(@UserIdInt int userId) {
315         try {
316             mBmgr.backupNowForUser(userId);
317         } catch (RemoteException e) {
318             handleRemoteException(e);
319         }
320     }
321 
doBackup(@serIdInt int userId)322     private void doBackup(@UserIdInt int userId) {
323         String pkg = nextArg();
324         if (pkg == null) {
325             showUsage();
326             return;
327         }
328 
329         try {
330             mBmgr.dataChangedForUser(userId, pkg);
331         } catch (RemoteException e) {
332             handleRemoteException(e);
333         }
334     }
335 
doFullTransportBackup(@serIdInt int userId)336     private void doFullTransportBackup(@UserIdInt int userId) {
337         System.out.println("Performing full transport backup");
338 
339         String pkg;
340         ArraySet<String> allPkgs = new ArraySet<String>();
341         while ((pkg = nextArg()) != null) {
342             allPkgs.add(pkg);
343         }
344         if (allPkgs.size() > 0) {
345             try {
346                 mBmgr.fullTransportBackupForUser(
347                         userId, allPkgs.toArray(new String[allPkgs.size()]));
348             } catch (RemoteException e) {
349                 handleRemoteException(e);
350             }
351         }
352     }
353 
354     // IBackupObserver generically usable for any backup/init operation
355     private static abstract class Observer extends IBackupObserver.Stub {
356         private final Object trigger = new Object();
357 
358         @GuardedBy("trigger")
359         private volatile boolean done = false;
360 
361         @Override
onUpdate(String currentPackage, BackupProgress backupProgress)362         public void onUpdate(String currentPackage, BackupProgress backupProgress) {
363         }
364 
365         @Override
onResult(String currentPackage, int status)366         public void onResult(String currentPackage, int status) {
367         }
368 
369         @Override
backupFinished(int status)370         public void backupFinished(int status) {
371             synchronized (trigger) {
372                 done = true;
373                 trigger.notify();
374             }
375         }
376 
done()377         public boolean done() {
378             return this.done;
379         }
380 
381         // Wait forever
waitForCompletion()382         public void waitForCompletion() {
383             waitForCompletion(0);
384         }
385 
386         // Wait for a given time and then give up
waitForCompletion(long timeout)387         public void waitForCompletion(long timeout) {
388             // The backupFinished() callback will throw the 'done' flag; we
389             // just sit and wait on that notification.
390             final long targetTime = SystemClock.elapsedRealtime() + timeout;
391             synchronized (trigger) {
392                 // Wait until either we're done, or we've reached a stated positive timeout
393                 while (!done && (timeout <= 0 || SystemClock.elapsedRealtime() < targetTime)) {
394                     try {
395                         trigger.wait(1000L);
396                     } catch (InterruptedException ex) {
397                     }
398                 }
399             }
400         }
401     }
402 
403     private static class BackupObserver extends Observer {
404         @Override
onUpdate(String currentPackage, BackupProgress backupProgress)405         public void onUpdate(String currentPackage, BackupProgress backupProgress) {
406             super.onUpdate(currentPackage, backupProgress);
407             System.out.println(
408                 "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
409                     + "/" + backupProgress.bytesExpected);
410         }
411 
412         @Override
onResult(String currentPackage, int status)413         public void onResult(String currentPackage, int status) {
414             super.onResult(currentPackage, status);
415             System.out.println("Package " + currentPackage + " with result: "
416                     + convertBackupStatusToString(status));
417         }
418 
419         @Override
backupFinished(int status)420         public void backupFinished(int status) {
421             super.backupFinished(status);
422             System.out.println("Backup finished with result: "
423                     + convertBackupStatusToString(status));
424             if (status == BackupManager.ERROR_BACKUP_CANCELLED) {
425                 System.out.println("Backups can be cancelled if a backup is already running, check "
426                                 + "backup dumpsys");
427             }
428         }
429     }
430 
convertBackupStatusToString(int errorCode)431     private static String convertBackupStatusToString(int errorCode) {
432         switch (errorCode) {
433             case BackupManager.SUCCESS:
434                 return "Success";
435             case BackupManager.ERROR_BACKUP_NOT_ALLOWED:
436                 return "Backup is not allowed";
437             case BackupManager.ERROR_PACKAGE_NOT_FOUND:
438                 return "Package not found";
439             case BackupManager.ERROR_TRANSPORT_ABORTED:
440                 return "Transport error";
441             case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED:
442                 return "Transport rejected package because it wasn't able to process it"
443                         + " at the time";
444             case BackupManager.ERROR_AGENT_FAILURE:
445                 return "Agent error";
446             case BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED:
447                 return "Size quota exceeded";
448             case BackupManager.ERROR_BACKUP_CANCELLED:
449                 return "Backup cancelled";
450             default:
451                 return "Unknown error";
452         }
453     }
454 
backupNowAllPackages(@serIdInt int userId, boolean nonIncrementalBackup, @Monitor int monitorState)455     private void backupNowAllPackages(@UserIdInt int userId, boolean nonIncrementalBackup,
456             @Monitor int monitorState) {
457         IPackageManager mPm =
458                 IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
459         if (mPm == null) {
460             System.err.println(PM_NOT_RUNNING_ERR);
461             return;
462         }
463         List<PackageInfo> installedPackages = null;
464         try {
465             installedPackages =  mPm.getInstalledPackages(0, userId).getList();
466         } catch (RemoteException e) {
467             System.err.println(e.toString());
468             System.err.println(PM_NOT_RUNNING_ERR);
469         }
470         if (installedPackages != null) {
471             String[] packages =
472                     installedPackages.stream().map(p -> p.packageName).toArray(String[]::new);
473             String[] filteredPackages = {};
474             try {
475                 filteredPackages = mBmgr.filterAppsEligibleForBackupForUser(userId, packages);
476             } catch (RemoteException e) {
477                 handleRemoteException(e);
478             }
479             backupNowPackages(userId, Arrays.asList(filteredPackages), nonIncrementalBackup,
480                     monitorState);
481         }
482     }
483 
backupNowPackages( @serIdInt int userId, List<String> packages, boolean nonIncrementalBackup, @Monitor int monitorState)484     private void backupNowPackages(
485             @UserIdInt int userId,
486             List<String> packages, boolean nonIncrementalBackup, @Monitor int monitorState) {
487         int flags = 0;
488         if (nonIncrementalBackup) {
489             flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP;
490         }
491         try {
492             BackupObserver observer = new BackupObserver();
493             BackupMonitor monitor =
494                     (monitorState != Monitor.OFF)
495                             ? new BackupMonitor(monitorState == Monitor.VERBOSE)
496                             : null;
497             int err = mBmgr.requestBackupForUser(
498                     userId,
499                     packages.toArray(new String[packages.size()]),
500                     observer,
501                     monitor,
502                     flags);
503             if (err == 0) {
504                 // Off and running -- wait for the backup to complete
505                 observer.waitForCompletion();
506             } else {
507                 System.err.println("Unable to run backup");
508             }
509         } catch (RemoteException e) {
510             handleRemoteException(e);
511         }
512     }
513 
doBackupNow(@serIdInt int userId)514     private void doBackupNow(@UserIdInt int userId) {
515         String pkg;
516         boolean backupAll = false;
517         boolean nonIncrementalBackup = false;
518         @Monitor int monitor = Monitor.OFF;
519         ArrayList<String> allPkgs = new ArrayList<String>();
520         while ((pkg = nextArg()) != null) {
521             if (pkg.equals("--all")) {
522                 backupAll = true;
523             } else if (pkg.equals("--non-incremental")) {
524                 nonIncrementalBackup = true;
525             } else if (pkg.equals("--incremental")) {
526                 nonIncrementalBackup = false;
527             } else if (pkg.equals("--monitor")) {
528                 monitor = Monitor.NORMAL;
529             } else if (pkg.equals("--monitor-verbose")) {
530                 monitor = Monitor.VERBOSE;
531             } else {
532                 if (!allPkgs.contains(pkg)) {
533                     allPkgs.add(pkg);
534                 }
535             }
536         }
537         if (backupAll) {
538             if (allPkgs.size() == 0) {
539                 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
540                         "incremental backup for all packages.");
541                 backupNowAllPackages(userId, nonIncrementalBackup, monitor);
542             } else {
543                 System.err.println("Provide only '--all' flag or list of packages.");
544             }
545         } else if (allPkgs.size() > 0) {
546             System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") +
547                     "incremental backup for " + allPkgs.size() +" requested packages.");
548             backupNowPackages(userId, allPkgs, nonIncrementalBackup, monitor);
549         } else {
550             System.err.println("Provide '--all' flag or list of packages.");
551         }
552     }
553 
doCancel(@serIdInt int userId)554     private void doCancel(@UserIdInt int userId) {
555         String arg = nextArg();
556         if ("backups".equals(arg)) {
557             try {
558                 mBmgr.cancelBackupsForUser(userId);
559             } catch (RemoteException e) {
560                 handleRemoteException(e);
561             }
562             return;
563         }
564 
565         System.err.println("Unknown command.");
566     }
567 
doTransport(@serIdInt int userId)568     private void doTransport(@UserIdInt int userId) {
569         try {
570             String which = nextArg();
571             if (which == null) {
572                 showUsage();
573                 return;
574             }
575 
576             if ("-c".equals(which)) {
577                 doTransportByComponent(userId);
578                 return;
579             }
580 
581             String old = mBmgr.selectBackupTransportForUser(userId, which);
582             if (old == null) {
583                 System.out.println("Unknown transport '" + which
584                         + "' specified; no changes made.");
585             } else {
586                 System.out.println("Selected transport " + which + " (formerly " + old + ")");
587             }
588 
589         } catch (RemoteException e) {
590             handleRemoteException(e);
591         }
592     }
593 
doTransportByComponent(@serIdInt int userId)594     private void doTransportByComponent(@UserIdInt int userId) {
595         String which = nextArg();
596         if (which == null) {
597             showUsage();
598             return;
599         }
600 
601         final CountDownLatch latch = new CountDownLatch(1);
602 
603         try {
604             mBmgr.selectBackupTransportAsyncForUser(
605                     userId,
606                     ComponentName.unflattenFromString(which),
607                     new ISelectBackupTransportCallback.Stub() {
608                         @Override
609                         public void onSuccess(String transportName) {
610                             System.out.println("Success. Selected transport: " + transportName);
611                             latch.countDown();
612                         }
613 
614                         @Override
615                         public void onFailure(int reason) {
616                             System.err.println("Failure. error=" + reason);
617                             latch.countDown();
618                         }
619                     });
620         } catch (RemoteException e) {
621             handleRemoteException(e);
622             return;
623         }
624 
625         try {
626             latch.await();
627         } catch (InterruptedException e) {
628             System.err.println("Operation interrupted.");
629         }
630     }
631 
doWipe(@serIdInt int userId)632     private void doWipe(@UserIdInt int userId) {
633         String transport = nextArg();
634         if (transport == null) {
635             showUsage();
636             return;
637         }
638 
639         String pkg = nextArg();
640         if (pkg == null) {
641             showUsage();
642             return;
643         }
644 
645         try {
646             mBmgr.clearBackupDataForUser(userId, transport, pkg);
647             System.out.println("Wiped backup data for " + pkg + " on " + transport);
648         } catch (RemoteException e) {
649             handleRemoteException(e);
650         }
651     }
652 
653     class InitObserver extends Observer {
654         public int result = BackupTransport.TRANSPORT_ERROR;
655 
656         @Override
backupFinished(int status)657         public void backupFinished(int status) {
658             super.backupFinished(status);
659             result = status;
660         }
661     }
662 
doInit(@serIdInt int userId)663     private void doInit(@UserIdInt int userId) {
664         ArraySet<String> transports = new ArraySet<>();
665         String transport;
666         while ((transport = nextArg()) != null) {
667             transports.add(transport);
668         }
669         if (transports.size() == 0) {
670             showUsage();
671             return;
672         }
673 
674         InitObserver observer = new InitObserver();
675         try {
676             System.out.println("Initializing transports: " + transports);
677             mBmgr.initializeTransportsForUser(
678                     userId, transports.toArray(new String[transports.size()]), observer);
679             observer.waitForCompletion(30*1000L);
680             System.out.println("Initialization result: " + observer.result);
681         } catch (RemoteException e) {
682             handleRemoteException(e);
683         }
684     }
685 
doList(@serIdInt int userId)686     private void doList(@UserIdInt int userId) {
687         String arg = nextArg();     // sets, transports, packages set#
688         if ("transports".equals(arg)) {
689             doListTransports(userId);
690             return;
691         }
692 
693         // The rest of the 'list' options work with a restore session on the current transport
694         try {
695             mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
696             if (mRestore == null) {
697                 System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
698                 return;
699             }
700 
701             if ("sets".equals(arg)) {
702                 doListRestoreSets();
703             }
704 
705             mRestore.endRestoreSession();
706         } catch (RemoteException e) {
707             handleRemoteException(e);
708         }
709     }
710 
doListTransports(@serIdInt int userId)711     private void doListTransports(@UserIdInt int userId) {
712         String arg = nextArg();
713 
714         try {
715             if ("-c".equals(arg)) {
716                 for (ComponentName transport : mBmgr.listAllTransportComponentsForUser(userId)) {
717                     System.out.println(transport.flattenToShortString());
718                 }
719                 return;
720             }
721 
722             String current = mBmgr.getCurrentTransportForUser(userId);
723             String[] transports = mBmgr.listAllTransportsForUser(userId);
724             if (transports == null || transports.length == 0) {
725                 System.out.println("No transports available.");
726                 return;
727             }
728 
729             for (String t : transports) {
730                 String pad = (t.equals(current)) ? "  * " : "    ";
731                 System.out.println(pad + t);
732             }
733         } catch (RemoteException e) {
734             handleRemoteException(e);
735         }
736     }
737 
doListRestoreSets()738     private void doListRestoreSets() {
739         try {
740             RestoreObserver observer = new RestoreObserver();
741             // TODO implement monitor here
742             int err = mRestore.getAvailableRestoreSets(observer, null);
743             if (err != 0) {
744                 System.out.println("Unable to request restore sets");
745             } else {
746                 observer.waitForCompletion();
747                 printRestoreSets(observer.sets);
748             }
749         } catch (RemoteException e) {
750             System.err.println(e.toString());
751             System.err.println(TRANSPORT_NOT_RUNNING_ERR);
752         }
753     }
754 
printRestoreSets(RestoreSet[] sets)755     private void printRestoreSets(RestoreSet[] sets) {
756         if (sets == null || sets.length == 0) {
757             System.out.println("No restore sets");
758             return;
759         }
760         for (RestoreSet s : sets) {
761             System.out.println("  " + Long.toHexString(s.token) + " : " + s.name);
762         }
763     }
764 
765     class RestoreObserver extends IRestoreObserver.Stub {
766         boolean done;
767         RestoreSet[] sets = null;
768 
restoreSetsAvailable(RestoreSet[] result)769         public void restoreSetsAvailable(RestoreSet[] result) {
770             synchronized (this) {
771                 sets = result;
772                 done = true;
773                 this.notify();
774             }
775         }
776 
restoreStarting(int numPackages)777         public void restoreStarting(int numPackages) {
778             System.out.println("restoreStarting: " + numPackages + " packages");
779         }
780 
onUpdate(int nowBeingRestored, String currentPackage)781         public void onUpdate(int nowBeingRestored, String currentPackage) {
782             System.out.println("onUpdate: " + nowBeingRestored + " = " + currentPackage);
783         }
784 
restoreFinished(int error)785         public void restoreFinished(int error) {
786             System.out.println("restoreFinished: " + error);
787             synchronized (this) {
788                 done = true;
789                 this.notify();
790             }
791         }
792 
793         /**
794          * Wait until either {@link #restoreFinished} or {@link #restoreStarting} is called.
795          * Once one is called, it clears the internal flag again, so that the same observer intance
796          * can be reused for a next operation.
797          */
waitForCompletion()798         public void waitForCompletion() {
799             // The restoreFinished() callback will throw the 'done' flag; we
800             // just sit and wait on that notification.
801             synchronized (this) {
802                 while (!this.done) {
803                     try {
804                         this.wait();
805                     } catch (InterruptedException ex) {
806                     }
807                 }
808                 done = false;
809             }
810         }
811     }
812 
doRestore(@serIdInt int userId)813     private void doRestore(@UserIdInt int userId) {
814         String arg = nextArg();
815         if (arg == null) {
816             showUsage();
817             return;
818         }
819 
820         if (arg.indexOf('.') >= 0 || arg.equals("android")) {
821             // it's a package name
822             doRestorePackage(arg);
823         } else {
824             try {
825                 @Monitor int monitor = Monitor.OFF;
826 
827                 long token = Long.parseLong(arg, 16);
828                 HashSet<String> filter = null;
829                 while ((arg = nextArg()) != null) {
830                     if (arg.equals("--monitor")) {
831                         monitor = Monitor.NORMAL;
832                     } else if (arg.equals("--monitor-verbose")) {
833                         monitor = Monitor.VERBOSE;
834                     } else {
835                         if (filter == null) filter = new HashSet<String>();
836                         filter.add(arg);
837                     }
838                 }
839 
840                 doRestoreAll(userId, token, filter, monitor);
841             } catch (NumberFormatException e) {
842                 showUsage();
843                 return;
844             }
845         }
846     }
847 
doRestorePackage(String pkg)848     private void doRestorePackage(String pkg) {
849         System.err.println("The syntax 'restore <package>' is no longer supported, please use ");
850         System.err.println("'restore <token> <package>'.");
851     }
852 
doRestoreAll(@serIdInt int userId, long token, HashSet<String> filter, @Monitor int monitorState)853     private void doRestoreAll(@UserIdInt int userId, long token, HashSet<String> filter,
854             @Monitor int monitorState) {
855         RestoreObserver observer = new RestoreObserver();
856 
857         try {
858             boolean didRestore = false;
859             mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
860             if (mRestore == null) {
861                 System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
862                 return;
863             }
864             RestoreSet[] sets = null;
865             BackupMonitor monitor =
866                     (monitorState != Monitor.OFF)
867                             ? new BackupMonitor(monitorState == Monitor.VERBOSE)
868                             : null;
869             int err = mRestore.getAvailableRestoreSets(observer, monitor);
870             if (err == 0) {
871                 observer.waitForCompletion();
872                 sets = observer.sets;
873                 if (sets != null) {
874                     for (RestoreSet s : sets) {
875                         if (s.token == token) {
876                             System.out.println("Scheduling restore: " + s.name);
877                             if (filter == null) {
878                                 didRestore = (mRestore.restoreAll(token, observer, monitor) == 0);
879                             } else {
880                                 String[] names = new String[filter.size()];
881                                 filter.toArray(names);
882                                 didRestore = (mRestore.restorePackages(token, observer, names,
883                                         monitor) == 0);
884                             }
885                             break;
886                         }
887                     }
888                 }
889             }
890             if (!didRestore) {
891                 if (sets == null || sets.length == 0) {
892                     System.out.println("No available restore sets; no restore performed");
893                 } else {
894                     System.out.println("No matching restore set token.  Available sets:");
895                     printRestoreSets(sets);
896                 }
897             }
898 
899             // if we kicked off a restore successfully, we have to wait for it
900             // to complete before we can shut down the restore session safely
901             if (didRestore) {
902                 observer.waitForCompletion();
903             }
904 
905             // once the restore has finished, close down the session and we're done
906             mRestore.endRestoreSession();
907 
908             System.out.println("done");
909         } catch (RemoteException e) {
910             handleRemoteException(e);
911         }
912     }
913 
doPrintAllowlist()914     private void doPrintAllowlist() {
915         try {
916             final String[] whitelist = mBmgr.getTransportWhitelist();
917             if (whitelist != null) {
918                 for (String transport : whitelist) {
919                     System.out.println(transport);
920                 }
921             }
922         } catch (RemoteException e) {
923             handleRemoteException(e);
924         }
925     }
926 
doActivateService(int userId)927     private void doActivateService(int userId) {
928         String arg = nextArg();
929         if (arg == null) {
930             showUsage();
931             return;
932         }
933 
934         try {
935             boolean activate = Boolean.parseBoolean(arg);
936             mBmgr.setBackupServiceActive(userId, activate);
937             System.out.println(
938                     "Backup service now "
939                             + (activate ? "activated" : "deactivated")
940                             + " for user "
941                             + userId);
942         } catch (RemoteException e) {
943             handleRemoteException(e);
944         }
945     }
946 
nextArg()947     private String nextArg() {
948         if (mNextArg >= mArgs.length) {
949             return null;
950         }
951         String arg = mArgs[mNextArg];
952         mNextArg++;
953         return arg;
954     }
955 
parseUserId()956     private int parseUserId() {
957         String arg = nextArg();
958         if ("--user".equals(arg)) {
959             return UserHandle.parseUserArg(nextArg());
960         } else {
961             mNextArg--;
962             return UserHandle.USER_SYSTEM;
963         }
964     }
965 
showUsage()966     private static void showUsage() {
967         System.err.println("usage: bmgr [--user <userId>] [backup|restore|list|transport|run]");
968         System.err.println("       bmgr backup PACKAGE");
969         System.err.println("       bmgr enable BOOL");
970         System.err.println("       bmgr enabled");
971         System.err.println("       bmgr list transports [-c]");
972         System.err.println("       bmgr list sets");
973         System.err.println("       bmgr transport WHICH|-c WHICH_COMPONENT");
974         System.err.println("       bmgr restore TOKEN [--monitor|--monitor-verbose]");
975         System.err.println("       bmgr restore TOKEN PACKAGE... [--monitor|--monitor-verbose]");
976         System.err.println("       bmgr run");
977         System.err.println("       bmgr wipe TRANSPORT PACKAGE");
978         System.err.println("       bmgr fullbackup PACKAGE...");
979         System.err.println("       bmgr backupnow [--monitor|--monitor-verbose] --all|PACKAGE...");
980         System.err.println("       bmgr cancel backups");
981         System.err.println("       bmgr init TRANSPORT...");
982         System.err.println("       bmgr activate BOOL");
983         System.err.println("       bmgr activated");
984         System.err.println("       bmgr autorestore BOOL");
985         System.err.println("       bmgr scheduling BOOL");
986         System.err.println("");
987         System.err.println("The '--user' option specifies the user on which the operation is run.");
988         System.err.println("It must be the first argument before the operation.");
989         System.err.println("The default value is 0 which is the system user.");
990         System.err.println("");
991         System.err.println("The 'backup' command schedules a backup pass for the named package.");
992         System.err.println("Note that the backup pass will effectively be a no-op if the package");
993         System.err.println("does not actually have changed data to store.");
994         System.err.println("");
995         System.err.println("The 'enable' command enables or disables the entire backup mechanism.");
996         System.err.println("If the argument is 'true' it will be enabled, otherwise it will be");
997         System.err.println("disabled.  When disabled, neither backup or restore operations will");
998         System.err.println("be performed.");
999         System.err.println("");
1000         System.err.println("The 'enabled' command reports the current enabled/disabled state of");
1001         System.err.println("the backup mechanism.");
1002         System.err.println("");
1003         System.err.println("The 'list transports' command reports the names of the backup transports");
1004         System.err.println("BackupManager is currently bound to. These names can be passed as arguments");
1005         System.err.println("to the 'transport' and 'wipe' commands.  The currently active transport");
1006         System.err.println("is indicated with a '*' character. If -c flag is used, all available");
1007         System.err.println("transport components on the device are listed. These can be used with");
1008         System.err.println("the component variant of 'transport' command.");
1009         System.err.println("");
1010         System.err.println("The 'list sets' command reports the token and name of each restore set");
1011         System.err.println("available to the device via the currently active transport.");
1012         System.err.println("");
1013         System.err.println("The 'transport' command designates the named transport as the currently");
1014         System.err.println("active one.  This setting is persistent across reboots. If -c flag is");
1015         System.err.println("specified, the following string is treated as a component name.");
1016         System.err.println("");
1017         System.err.println("The 'restore' command when given just a restore token initiates a full-system");
1018         System.err.println("restore operation from the currently active transport.  It will deliver");
1019         System.err.println("the restore set designated by the TOKEN argument to each application");
1020         System.err.println("that had contributed data to that restore set.");
1021         System.err.println("    --monitor flag prints monitor events (important events and errors");
1022         System.err.println("              encountered during restore).");
1023         System.err.println("    --monitor-verbose flag prints monitor events with all keys.");
1024         System.err.println("");
1025         System.err.println("The 'restore' command when given a token and one or more package names");
1026         System.err.println("initiates a restore operation of just those given packages from the restore");
1027         System.err.println("set designated by the TOKEN argument.  It is effectively the same as the");
1028         System.err.println("'restore' operation supplying only a token, but applies a filter to the");
1029         System.err.println("set of applications to be restored.");
1030         System.err.println("    --monitor flag prints monitor events (important events and errors");
1031         System.err.println("              encountered during restore).");
1032         System.err.println("    --monitor-verbose flag prints monitor events with all keys.");
1033         System.err.println("");
1034         System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
1035         System.err.println("immediately, without the usual waiting period for batching together");
1036         System.err.println("data changes.");
1037         System.err.println("");
1038         System.err.println("The 'wipe' command causes all backed-up data for the given package to be");
1039         System.err.println("erased from the given transport's storage.  The next backup operation");
1040         System.err.println("that the given application performs will rewrite its entire data set.");
1041         System.err.println("Transport names to use here are those reported by 'list transports'.");
1042         System.err.println("");
1043         System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more");
1044         System.err.println("packages.  The data is sent via the currently active transport.");
1045         System.err.println("");
1046         System.err.println("The 'backupnow' command runs an immediate backup for one or more packages.");
1047         System.err.println("    --all flag runs backup for all eligible packages.");
1048         System.err.println("    --monitor flag prints monitor events (important events and errors");
1049         System.err.println("              encountered during backup).");
1050         System.err.println("    --monitor-verbose flag prints monitor events with all keys.");
1051         System.err.println("For each package it will run key/value or full data backup ");
1052         System.err.println("depending on the package's manifest declarations.");
1053         System.err.println("The data is sent via the currently active transport.");
1054         System.err.println("");
1055         System.err.println("The 'cancel backups' command cancels all running backups.");
1056         System.err.println("");
1057         System.err.println("The 'init' command initializes the given transports, wiping all data");
1058         System.err.println("from their backing data stores.");
1059         System.err.println("");
1060         System.err.println("The 'activate' command activates or deactivates the backup service.");
1061         System.err.println("If the argument is 'true' it will be activated, otherwise it will be");
1062         System.err.println("deactivated. When deactivated, the service will not be running and no");
1063         System.err.println("operations can be performed until activation.");
1064         System.err.println("");
1065         System.err.println("The 'activated' command reports the current activated/deactivated");
1066         System.err.println("state of the backup mechanism.");
1067         System.err.println("");
1068         System.err.println("The 'autorestore' command enables or disables automatic restore when");
1069         System.err.println("a new package is installed.");
1070         System.err.println("");
1071         System.err.println("The 'scheduling' command enables or disables backup scheduling in the");
1072         System.err.println("framework.");
1073     }
1074 
1075     private static class BackupMonitor extends IBackupManagerMonitor.Stub {
1076         private final boolean mVerbose;
1077 
BackupMonitor(boolean verbose)1078         private BackupMonitor(boolean verbose) {
1079             mVerbose = verbose;
1080         }
1081 
1082         @Override
onEvent(Bundle event)1083         public void onEvent(Bundle event) throws RemoteException {
1084             StringBuilder out = new StringBuilder();
1085             int id = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
1086             int category = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY);
1087             out.append("=> Event{").append(eventCategoryToString(category));
1088             out.append(" / ").append(eventIdToString(id));
1089             String packageName = event.getString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME);
1090             if (packageName != null) {
1091                 out.append(" : package = ").append(packageName);
1092                 if (event.containsKey(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION)) {
1093                     long version =
1094                             event.getLong(
1095                                     BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION);
1096                     out.append("(v").append(version).append(")");
1097                 }
1098             }
1099             if (event.containsKey(BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS)) {
1100                 ArrayList<BackupRestoreEventLogger.DataTypeResult> results =
1101                         event.getParcelableArrayList(
1102                                 BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
1103                                 BackupRestoreEventLogger.DataTypeResult.class);
1104                 out.append(", results = [");
1105                 for (BackupRestoreEventLogger.DataTypeResult result : results) {
1106                     out.append("\n{\n\tdataType: ");
1107                     out.append(result.getDataType());
1108                     out.append("\n\tsuccessCount: ");
1109                     out.append(result.getSuccessCount());
1110                     out.append("\n\tfailCount: ");
1111                     out.append(result.getFailCount());
1112                     out.append("\n\tmetadataHash: ");
1113                     out.append(Arrays.toString(result.getMetadataHash()));
1114 
1115                     if (!result.getErrors().isEmpty()) {
1116                         out.append("\n\terrors: [");
1117                         for (String error : result.getErrors().keySet()) {
1118                             out.append(error);
1119                             out.append(": ");
1120                             out.append(result.getErrors().get(error));
1121                             out.append(";");
1122                         }
1123                         out.append("]");
1124                     }
1125                     out.append("\n}");
1126 
1127                 }
1128                 out.append("]");
1129             }
1130             if (mVerbose) {
1131                 Set<String> remainingKeys = new ArraySet<>(event.keySet());
1132                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_ID);
1133                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY);
1134                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME);
1135                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION);
1136                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION);
1137                 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS);
1138                 if (!remainingKeys.isEmpty()) {
1139                     out.append(", other keys =");
1140                     for (String key : remainingKeys) {
1141                         out.append(" ").append(key);
1142                     }
1143                 }
1144             }
1145             out.append("}");
1146             System.out.println(out.toString());
1147         }
1148     }
1149 
eventCategoryToString(int eventCategory)1150     private static String eventCategoryToString(int eventCategory) {
1151         switch (eventCategory) {
1152             case BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT:
1153                 return "TRANSPORT";
1154             case BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT:
1155                 return "AGENT";
1156             case BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY:
1157                 return "BACKUP_MANAGER_POLICY";
1158             default:
1159                 return "UNKNOWN_CATEGORY";
1160         }
1161     }
1162 
eventIdToString(int eventId)1163     private static String eventIdToString(int eventId) {
1164         switch (eventId) {
1165             case BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL:
1166                 return "FULL_BACKUP_CANCEL";
1167             case BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY:
1168                 return "ILLEGAL_KEY";
1169             case BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND:
1170                 return "NO_DATA_TO_SEND";
1171             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE:
1172                 return "PACKAGE_INELIGIBLE";
1173             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT:
1174                 return "PACKAGE_KEY_VALUE_PARTICIPANT";
1175             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED:
1176                 return "PACKAGE_STOPPED";
1177             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND:
1178                 return "PACKAGE_NOT_FOUND";
1179             case BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED:
1180                 return "BACKUP_DISABLED";
1181             case BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED:
1182                 return "DEVICE_NOT_PROVISIONED";
1183             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT:
1184                 return "PACKAGE_TRANSPORT_NOT_PRESENT";
1185             case BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT:
1186                 return "ERROR_PREFLIGHT";
1187             case BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT:
1188                 return "QUOTA_HIT_PREFLIGHT";
1189             case BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP:
1190                 return "EXCEPTION_FULL_BACKUP";
1191             case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL:
1192                 return "KEY_VALUE_BACKUP_CANCEL";
1193             case BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE:
1194                 return "NO_RESTORE_METADATA_AVAILABLE";
1195             case BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED:
1196                 return "NO_PM_METADATA_RECEIVED";
1197             case BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA:
1198                 return "PM_AGENT_HAS_NO_METADATA";
1199             case BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT:
1200                 return "LOST_TRANSPORT";
1201             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT:
1202                 return "PACKAGE_NOT_PRESENT";
1203             case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER:
1204                 return "RESTORE_VERSION_HIGHER";
1205             case BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT:
1206                 return "APP_HAS_NO_AGENT";
1207             case BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH:
1208                 return "SIGNATURE_MISMATCH";
1209             case BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT:
1210                 return "CANT_FIND_AGENT";
1211             case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT:
1212                 return "KEY_VALUE_RESTORE_TIMEOUT";
1213             case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION:
1214                 return "RESTORE_ANY_VERSION";
1215             case BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH:
1216                 return "VERSIONS_MATCH";
1217             case BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER:
1218                 return "VERSION_OF_BACKUP_OLDER";
1219             case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH:
1220                 return "FULL_RESTORE_SIGNATURE_MISMATCH";
1221             case BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT:
1222                 return "SYSTEM_APP_NO_AGENT";
1223             case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE:
1224                 return "FULL_RESTORE_ALLOW_BACKUP_FALSE";
1225             case BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED:
1226                 return "APK_NOT_INSTALLED";
1227             case BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK:
1228                 return "CANNOT_RESTORE_WITHOUT_APK";
1229             case BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE:
1230                 return "MISSING_SIGNATURE";
1231             case BackupManagerMonitor.LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE:
1232                 return "EXPECTED_DIFFERENT_PACKAGE";
1233             case BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION:
1234                 return "UNKNOWN_VERSION";
1235             case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT:
1236                 return "FULL_RESTORE_TIMEOUT";
1237             case BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST:
1238                 return "CORRUPT_MANIFEST";
1239             case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH:
1240                 return "WIDGET_METADATA_MISMATCH";
1241             case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION:
1242                 return "WIDGET_UNKNOWN_VERSION";
1243             case BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES:
1244                 return "NO_PACKAGES";
1245             case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL:
1246                 return "TRANSPORT_IS_NULL";
1247             case BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS:
1248                 return "AGENT_LOGGING_RESULTS";
1249             case BackupManagerMonitor.LOG_EVENT_ID_START_SYSTEM_RESTORE:
1250                 return "START_SYSTEM_RESTORE";
1251             case BackupManagerMonitor.LOG_EVENT_ID_START_RESTORE_AT_INSTALL:
1252                 return "START_RESTORE_AT_INSTALL";
1253             case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_ERROR_DURING_START_RESTORE:
1254                 return "TRANSPORT_ERROR_DURING_START_RESTORE";
1255             case BackupManagerMonitor.LOG_EVENT_ID_CANNOT_GET_NEXT_PKG_NAME:
1256                 return "CANNOT_GET_NEXT_PKG_NAME";
1257             case BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_RESTORE_TYPE:
1258                 return "UNKNOWN_RESTORE_TYPE";
1259             case BackupManagerMonitor.LOG_EVENT_ID_KV_RESTORE:
1260                 return "KV_RESTORE";
1261             case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE:
1262                 return "FULL_RESTORE";
1263             case BackupManagerMonitor.LOG_EVENT_ID_NO_NEXT_RESTORE_TARGET:
1264                 return "NO_NEXT_RESTORE_TARGET";
1265             case BackupManagerMonitor.LOG_EVENT_ID_KV_AGENT_ERROR:
1266                 return "KV_AGENT_ERROR";
1267             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_RESTORE_FINISHED:
1268                 return "PACKAGE_RESTORE_FINISHED";
1269             case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_ERROR_KV_RESTORE:
1270                 return "TRANSPORT_ERROR_KV_RESTORE";
1271             case BackupManagerMonitor.LOG_EVENT_ID_NO_FEEDER_THREAD:
1272                 return "NO_FEEDER_THREAD";
1273             case BackupManagerMonitor.LOG_EVENT_ID_FULL_AGENT_ERROR:
1274                 return "FULL_AGENT_ERROR";
1275             case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_ERROR_FULL_RESTORE:
1276                 return "TRANSPORT_ERROR_FULL_RESTORE";
1277             case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_COMPLETE:
1278                 return "RESTORE_COMPLETE";
1279             case BackupManagerMonitor.LOG_EVENT_ID_START_PACKAGE_RESTORE:
1280                 return "START_PACKAGE_RESTORE";
1281             case BackupManagerMonitor.LOG_EVENT_ID_AGENT_FAILURE:
1282                 return "AGENT_FAILURE";
1283             case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_AT_INSTALL_INVOKED:
1284                 return "RESTORE_AT_INSTALL_INVOKED";
1285             case BackupManagerMonitor.LOG_EVENT_ID_SKIP_RESTORE_AT_INSTALL:
1286                 return "SKIP_RESTORE_AT_INSTALL";
1287             case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_ACCEPTED_FOR_RESTORE:
1288                 return "PACKAGE_ACCEPTED_FOR_RESTORE";
1289             case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_DATA_DOES_NOT_BELONG_TO_PACKAGE:
1290                 return "RESTORE_DATA_DOES_NOT_BELONG_TO_PACKAGE";
1291             case BackupManagerMonitor.LOG_EVENT_ID_UNABLE_TO_CREATE_AGENT_FOR_RESTORE:
1292                 return "UNABLE_TO_CREATE_AGENT_FOR_RESTORE";
1293             case BackupManagerMonitor.LOG_EVENT_ID_AGENT_CRASHED_BEFORE_RESTORE_DATA_IS_SENT:
1294                 return "AGENT_CRASHED_BEFORE_RESTORE_DATA_IS_SEN";
1295             case BackupManagerMonitor.LOG_EVENT_ID_FAILED_TO_SEND_DATA_TO_AGENT_DURING_RESTORE:
1296                 return "FAILED_TO_SEND_DATA_TO_AGENT_DURING_RESTORE";
1297             case BackupManagerMonitor.LOG_EVENT_ID_AGENT_FAILURE_DURING_RESTORE:
1298                 return "AGENT_FAILURE_DURING_RESTORE";
1299             case BackupManagerMonitor.LOG_EVENT_ID_FAILED_TO_READ_DATA_FROM_TRANSPORT:
1300                 return "FAILED_TO_READ_DATA_FROM_TRANSPORT";
1301             default:
1302                 return "UNKNOWN_ID";
1303         }
1304     }
1305 
1306     @IntDef({Monitor.OFF, Monitor.NORMAL, Monitor.VERBOSE})
1307     @Retention(RetentionPolicy.SOURCE)
1308     private @interface Monitor {
1309         int OFF = 0;
1310         int NORMAL = 1;
1311         int VERBOSE = 2;
1312     }
1313 }
1314