class ActiveRestoreSession extends IRestoreSession.Stub {

    public synchronized int restorePackage(String packageName, IRestoreObserver observer,
            IBackupManagerMonitor monitor) {
        if (DEBUG) {
            Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer
                    + "monitor=" + monitor);
        }

        if (mEnded) {
            throw new IllegalStateException("Restore session already ended");
        }

        if (mTimedOut) {
            Slog.i(TAG, "Session already timed out");
            return -1;
        }

        if (mPackageName != null) {
            if (!mPackageName.equals(packageName)) {
                Slog.e(TAG, "Ignoring attempt to restore pkg=" + packageName
                        + " on session for package " + mPackageName);
                return -1;
            }
        }

        final PackageInfo app;
        try {
            app = mBackupManagerService.getPackageManager().getPackageInfoAsUser(
                    packageName, 0, mUserId);
        } catch (NameNotFoundException nnf) {
            Slog.w(TAG, "Asked to restore nonexistent pkg " + packageName);
            return -1;
        }

        // If the caller is not privileged and is not coming from the target
        // app's uid, throw a permission exception back to the caller.
        int perm = mBackupManagerService.getContext().checkPermission(
                android.Manifest.permission.BACKUP,
                Binder.getCallingPid(), Binder.getCallingUid());
        if ((perm == PackageManager.PERMISSION_DENIED) &&
                (app.applicationInfo.uid != Binder.getCallingUid())) {
            Slog.w(TAG, "restorePackage: bad packageName=" + packageName
                    + " or calling uid=" + Binder.getCallingUid());
            throw new SecurityException("No permission to restore other packages");
        }

        if (!mTransportManager.isTransportRegistered(mTransportName)) {
            Slog.e(TAG, "Transport " + mTransportName + " not registered");
            return -1;
        }

        // So far so good; we're allowed to try to restore this package.
        long oldId = Binder.clearCallingIdentity();
        try {
            // Check whether there is data for it in the current dataset, falling back
            // to the ancestral dataset if not.
            long token = mBackupManagerService.getAvailableRestoreToken(packageName);
            if (DEBUG) {
                Slog.v(TAG, "restorePackage pkg=" + packageName
                        + " token=" + Long.toHexString(token));
            }

            // If we didn't come up with a place to look -- no ancestral dataset and
            // the app has never been backed up from this device -- there's nothing
            // to do but return failure.
            if (token == 0) {
                if (DEBUG) {
                    Slog.w(TAG, "No data available for this package; not restoring");
                }
                return -1;
            }

            return sendRestoreToHandlerLocked(
                    (transportClient, listener) ->
                            RestoreParams.createForSinglePackage(
                                    transportClient,
                                    observer,
                                    monitor,
                                    token,
                                    app,
                                    listener),
                    "RestoreSession.restorePackage(" + packageName + ")");
        } finally {
            Binder.restoreCallingIdentity(oldId);
        }
    }

    public  ActiveRestoreSession(
            UserBackupManagerService backupManagerService,
            @Nullable String packageName,
            String transportName);

}