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