1*b7c941bbSAndroid Build Coastguard Worker /* 2*b7c941bbSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project 3*b7c941bbSAndroid Build Coastguard Worker * 4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*b7c941bbSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*b7c941bbSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*b7c941bbSAndroid Build Coastguard Worker * 8*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*b7c941bbSAndroid Build Coastguard Worker * 10*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*b7c941bbSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*b7c941bbSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*b7c941bbSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*b7c941bbSAndroid Build Coastguard Worker * limitations under the License 15*b7c941bbSAndroid Build Coastguard Worker */ 16*b7c941bbSAndroid Build Coastguard Worker 17*b7c941bbSAndroid Build Coastguard Worker package android.cts.backup.fullbackuponlyapp; 18*b7c941bbSAndroid Build Coastguard Worker 19*b7c941bbSAndroid Build Coastguard Worker import android.app.backup.BackupAgent; 20*b7c941bbSAndroid Build Coastguard Worker import android.app.backup.BackupDataInput; 21*b7c941bbSAndroid Build Coastguard Worker import android.app.backup.BackupDataOutput; 22*b7c941bbSAndroid Build Coastguard Worker 23*b7c941bbSAndroid Build Coastguard Worker import android.os.ParcelFileDescriptor; 24*b7c941bbSAndroid Build Coastguard Worker import android.util.Log; 25*b7c941bbSAndroid Build Coastguard Worker 26*b7c941bbSAndroid Build Coastguard Worker import java.io.BufferedInputStream; 27*b7c941bbSAndroid Build Coastguard Worker import java.io.BufferedOutputStream; 28*b7c941bbSAndroid Build Coastguard Worker import java.io.DataOutputStream; 29*b7c941bbSAndroid Build Coastguard Worker import java.io.File; 30*b7c941bbSAndroid Build Coastguard Worker import java.io.FileInputStream; 31*b7c941bbSAndroid Build Coastguard Worker import java.io.FileNotFoundException; 32*b7c941bbSAndroid Build Coastguard Worker import java.io.FileOutputStream; 33*b7c941bbSAndroid Build Coastguard Worker import java.io.IOException; 34*b7c941bbSAndroid Build Coastguard Worker 35*b7c941bbSAndroid Build Coastguard Worker /** 36*b7c941bbSAndroid Build Coastguard Worker * BackupAgent for test apps in {@link android.cts.backup.fullbackuponlyapp} package. 37*b7c941bbSAndroid Build Coastguard Worker * Performs backup/restore of the file provided by {@link FullBackupOnlyTest}. 38*b7c941bbSAndroid Build Coastguard Worker * 39*b7c941bbSAndroid Build Coastguard Worker * Implementation of key/value backup methods is based on the examples from 40*b7c941bbSAndroid Build Coastguard Worker * https://developer.android.com/guide/topics/data/keyvaluebackup.html 41*b7c941bbSAndroid Build Coastguard Worker */ 42*b7c941bbSAndroid Build Coastguard Worker public class FullBackupOnlyBackupAgent extends BackupAgent { 43*b7c941bbSAndroid Build Coastguard Worker private static final String TAG = "FullBackupOnlyBA"; 44*b7c941bbSAndroid Build Coastguard Worker 45*b7c941bbSAndroid Build Coastguard Worker private static final String BACKUP_KEY = "full_backup_only_key"; 46*b7c941bbSAndroid Build Coastguard Worker private static final int DEFAULT_VALUE = -1; 47*b7c941bbSAndroid Build Coastguard Worker 48*b7c941bbSAndroid Build Coastguard Worker /** Get the value saved in the shared preference and back it up. */ 49*b7c941bbSAndroid Build Coastguard Worker @Override onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)50*b7c941bbSAndroid Build Coastguard Worker public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, 51*b7c941bbSAndroid Build Coastguard Worker ParcelFileDescriptor newState) throws IOException { 52*b7c941bbSAndroid Build Coastguard Worker Log.i(TAG, "onBackup"); 53*b7c941bbSAndroid Build Coastguard Worker 54*b7c941bbSAndroid Build Coastguard Worker File fileToBackup = FullBackupOnlyTest.getKeyValueBackupFile(this); 55*b7c941bbSAndroid Build Coastguard Worker byte[] buffer = readFileToBytes(fileToBackup); 56*b7c941bbSAndroid Build Coastguard Worker 57*b7c941bbSAndroid Build Coastguard Worker // Send the data to the Backup Manager via the BackupDataOutput 58*b7c941bbSAndroid Build Coastguard Worker int len = buffer.length; 59*b7c941bbSAndroid Build Coastguard Worker data.writeEntityHeader(BACKUP_KEY, len); 60*b7c941bbSAndroid Build Coastguard Worker data.writeEntityData(buffer, len); 61*b7c941bbSAndroid Build Coastguard Worker } 62*b7c941bbSAndroid Build Coastguard Worker 63*b7c941bbSAndroid Build Coastguard Worker /** Get the value from backup and save it in the shared preference. */ 64*b7c941bbSAndroid Build Coastguard Worker @Override onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)65*b7c941bbSAndroid Build Coastguard Worker public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) 66*b7c941bbSAndroid Build Coastguard Worker throws IOException { 67*b7c941bbSAndroid Build Coastguard Worker Log.i(TAG, "onRestore"); 68*b7c941bbSAndroid Build Coastguard Worker int value = DEFAULT_VALUE; 69*b7c941bbSAndroid Build Coastguard Worker 70*b7c941bbSAndroid Build Coastguard Worker // There should be only one entity, but the safest 71*b7c941bbSAndroid Build Coastguard Worker // way to consume it is using a while loop 72*b7c941bbSAndroid Build Coastguard Worker while (data.readNextHeader()) { 73*b7c941bbSAndroid Build Coastguard Worker String key = data.getKey(); 74*b7c941bbSAndroid Build Coastguard Worker int dataSize = data.getDataSize(); 75*b7c941bbSAndroid Build Coastguard Worker 76*b7c941bbSAndroid Build Coastguard Worker // If the key is ours (for saving top score). Note this key was used when 77*b7c941bbSAndroid Build Coastguard Worker // we wrote the backup entity header 78*b7c941bbSAndroid Build Coastguard Worker if (BACKUP_KEY.equals(key)) { 79*b7c941bbSAndroid Build Coastguard Worker // Copy data from BackupDataInput and write it into the file. 80*b7c941bbSAndroid Build Coastguard Worker byte[] dataBuf = new byte[dataSize]; 81*b7c941bbSAndroid Build Coastguard Worker data.readEntityData(dataBuf, 0, dataSize); 82*b7c941bbSAndroid Build Coastguard Worker 83*b7c941bbSAndroid Build Coastguard Worker File fileToRestore = FullBackupOnlyTest.getKeyValueBackupFile(this); 84*b7c941bbSAndroid Build Coastguard Worker 85*b7c941bbSAndroid Build Coastguard Worker try (BufferedOutputStream bos = new BufferedOutputStream( 86*b7c941bbSAndroid Build Coastguard Worker new FileOutputStream(fileToRestore))) { 87*b7c941bbSAndroid Build Coastguard Worker bos.write(dataBuf, 0, dataBuf.length); 88*b7c941bbSAndroid Build Coastguard Worker } 89*b7c941bbSAndroid Build Coastguard Worker } else { 90*b7c941bbSAndroid Build Coastguard Worker // We don't know this entity key. Shouldn't happen. 91*b7c941bbSAndroid Build Coastguard Worker throw new RuntimeException("Unexpected key in the backup data"); 92*b7c941bbSAndroid Build Coastguard Worker } 93*b7c941bbSAndroid Build Coastguard Worker } 94*b7c941bbSAndroid Build Coastguard Worker 95*b7c941bbSAndroid Build Coastguard Worker // Finally, write to the state blob (newState) that describes the restored data 96*b7c941bbSAndroid Build Coastguard Worker FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor()); 97*b7c941bbSAndroid Build Coastguard Worker DataOutputStream out = new DataOutputStream(outstream); 98*b7c941bbSAndroid Build Coastguard Worker out.writeInt(value); 99*b7c941bbSAndroid Build Coastguard Worker } 100*b7c941bbSAndroid Build Coastguard Worker 101*b7c941bbSAndroid Build Coastguard Worker readFileToBytes(File file)102*b7c941bbSAndroid Build Coastguard Worker private byte[] readFileToBytes(File file) { 103*b7c941bbSAndroid Build Coastguard Worker int size = (int) file.length(); 104*b7c941bbSAndroid Build Coastguard Worker byte[] bytes = new byte[size]; 105*b7c941bbSAndroid Build Coastguard Worker try { 106*b7c941bbSAndroid Build Coastguard Worker BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file)); 107*b7c941bbSAndroid Build Coastguard Worker buf.read(bytes, 0, bytes.length); 108*b7c941bbSAndroid Build Coastguard Worker buf.close(); 109*b7c941bbSAndroid Build Coastguard Worker } catch (FileNotFoundException e) { 110*b7c941bbSAndroid Build Coastguard Worker throw new RuntimeException("Key/value file not found", e); 111*b7c941bbSAndroid Build Coastguard Worker } catch (IOException e) { 112*b7c941bbSAndroid Build Coastguard Worker throw new RuntimeException("Error reading key/value file", e); 113*b7c941bbSAndroid Build Coastguard Worker } 114*b7c941bbSAndroid Build Coastguard Worker return bytes; 115*b7c941bbSAndroid Build Coastguard Worker } 116*b7c941bbSAndroid Build Coastguard Worker } 117