1a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry/* 2a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * Copyright (C) 2016 The Android Open Source Project 3a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * 4a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * Licensed under the Apache License, Version 2.0 (the "License"); 5a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * you may not use this file except in compliance with the License. 6a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * You may obtain a copy of the License at 7a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * 8a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * http://www.apache.org/licenses/LICENSE-2.0 9a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * 10a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * Unless required by applicable law or agreed to in writing, software 11a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * distributed under the License is distributed on an "AS IS" BASIS, 12a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * See the License for the specific language governing permissions and 14a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * limitations under the License 15a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry */ 16a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 17a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastrypackage com.android.providers.blockednumber; 18a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 19a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.annotation.Nullable; 20a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.app.backup.BackupAgent; 21a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.app.backup.BackupDataInput; 22a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.app.backup.BackupDataOutput; 23a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.content.ContentResolver; 24a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.content.ContentValues; 25a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.database.Cursor; 26a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.os.ParcelFileDescriptor; 27a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.provider.BlockedNumberContract; 28a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport android.util.Log; 29a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 30a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport libcore.io.IoUtils; 31a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 32a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.ByteArrayInputStream; 33a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.ByteArrayOutputStream; 34a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.DataInputStream; 35a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.DataOutputStream; 36a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.FileInputStream; 37a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.FileOutputStream; 38a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.io.IOException; 39a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.util.ArrayList; 40a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.util.List; 41a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.util.SortedSet; 42a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastryimport java.util.TreeSet; 43a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 44a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry/** 45a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry * A backup agent to enable backup and restore of blocked numbers. 46a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry */ 47a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastrypublic class BlockedNumberBackupAgent extends BackupAgent { 48a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static final String[] BLOCKED_NUMBERS_PROJECTION = new String[] { 49a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BlockedNumberContract.BlockedNumbers.COLUMN_ID, 50a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER, 51a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BlockedNumberContract.BlockedNumbers.COLUMN_E164_NUMBER, 52a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry }; 53a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static final String TAG = "BlockedNumberBackup"; 54a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static final int VERSION = 1; 55a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE. 56a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 57a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry @Override 58a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput backupDataOutput, 59a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry ParcelFileDescriptor newState) throws IOException { 60a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry logV("Backing up blocked numbers."); 61a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 62a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry DataInputStream dataInputStream = 63a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry new DataInputStream(new FileInputStream(oldState.getFileDescriptor())); 64a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final BackupState state; 65a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 66a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry state = readState(dataInputStream); 67a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } finally { 68a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry IoUtils.closeQuietly(dataInputStream); 69a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 70a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 71a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry runBackup(state, backupDataOutput, getAllBlockedNumbers()); 72a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 73a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry DataOutputStream dataOutputStream = 74a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry new DataOutputStream(new FileOutputStream(newState.getFileDescriptor())); 75a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 76a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry writeNewState(dataOutputStream, state); 77a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } finally { 78a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.close(); 79a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 80a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 81a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 82a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry @Override 83a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry public void onRestore(BackupDataInput data, int appVersionCode, 84a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry ParcelFileDescriptor newState) throws IOException { 85a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry logV("Restoring blocked numbers."); 86a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 87a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry while (data.readNextHeader()) { 88a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BackedUpBlockedNumber blockedNumber = readBlockedNumberFromData(data); 89a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (blockedNumber != null) { 90a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry writeToProvider(blockedNumber); 91a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 92a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 93a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 94a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 95a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private BackupState readState(DataInputStream dataInputStream) throws IOException { 96a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry int version = VERSION; 97a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (dataInputStream.available() > 0) { 98a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry version = dataInputStream.readInt(); 99a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 100a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BackupState state = new BackupState(version, new TreeSet<Integer>()); 101a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry while (dataInputStream.available() > 0) { 102a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry state.ids.add(dataInputStream.readInt()); 103a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 104a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return state; 105a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 106a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 107a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void runBackup(BackupState state, BackupDataOutput backupDataOutput, 108a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Iterable<BackedUpBlockedNumber> allBlockedNumbers) throws IOException { 109a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry SortedSet<Integer> deletedBlockedNumbers = new TreeSet<>(state.ids); 110a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 111a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry for (BackedUpBlockedNumber blockedNumber : allBlockedNumbers) { 112a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (state.ids.contains(blockedNumber.id)) { 113a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry // Existing blocked number: do not delete. 114a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry deletedBlockedNumbers.remove(blockedNumber.id); 115a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } else { 116a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry logV("Adding blocked number to backup: " + blockedNumber); 117a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry // New blocked number 118a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry addToBackup(backupDataOutput, blockedNumber); 119a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry state.ids.add(blockedNumber.id); 120a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 121a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 122a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 123a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry for (int id : deletedBlockedNumbers) { 124a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry logV("Removing blocked number from backup: " + id); 125a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry removeFromBackup(backupDataOutput, id); 126a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry state.ids.remove(id); 127a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 128a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 129a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 130a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void addToBackup(BackupDataOutput output, BackedUpBlockedNumber blockedNumber) 131a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry throws IOException { 132a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 133a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry DataOutputStream dataOutputStream = new DataOutputStream(outputStream); 134a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeInt(VERSION); 135a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry writeString(dataOutputStream, blockedNumber.originalNumber); 136a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry writeString(dataOutputStream, blockedNumber.e164Number); 137a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.flush(); 138a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 139a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry output.writeEntityHeader(Integer.toString(blockedNumber.id), outputStream.size()); 140a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry output.writeEntityData(outputStream.toByteArray(), outputStream.size()); 141a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 142a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 143a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void writeString(DataOutputStream dataOutputStream, @Nullable String value) 144a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry throws IOException { 145a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (value == null) { 146a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeBoolean(false); 147a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } else { 148a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeBoolean(true); 149a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeUTF(value); 150a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 151a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 152a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 153a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry @Nullable 154a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private String readString(DataInputStream dataInputStream) 155a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry throws IOException { 156a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (dataInputStream.readBoolean()) { 157a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return dataInputStream.readUTF(); 158a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } else { 159a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return null; 160a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 161a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 162a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 163a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void removeFromBackup(BackupDataOutput output, int id) throws IOException { 164a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry output.writeEntityHeader(Integer.toString(id), -1); 165a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 166a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 167a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private Iterable<BackedUpBlockedNumber> getAllBlockedNumbers() { 168a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry List<BackedUpBlockedNumber> blockedNumbers = new ArrayList<>(); 169a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry ContentResolver resolver = getContentResolver(); 170a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Cursor cursor = resolver.query( 171a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BlockedNumberContract.BlockedNumbers.CONTENT_URI, BLOCKED_NUMBERS_PROJECTION, null, 172a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry null, null); 173a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (cursor != null) { 174a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 175a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry while (cursor.moveToNext()) { 176a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry blockedNumbers.add(createBlockedNumberFromCursor(cursor)); 177a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 178a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } finally { 179a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry cursor.close(); 180a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 181a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 182a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return blockedNumbers; 183a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 184a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 185a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private BackedUpBlockedNumber createBlockedNumberFromCursor(Cursor cursor) { 186a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return new BackedUpBlockedNumber( 187a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry cursor.getInt(0), cursor.getString(1), cursor.getString(2)); 188a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 189a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 190a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void writeNewState(DataOutputStream dataOutputStream, BackupState state) 191a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry throws IOException { 192a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeInt(VERSION); 193a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry for (int i : state.ids) { 194a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataOutputStream.writeInt(i); 195a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 196a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 197a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 198a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry @Nullable 199a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private BackedUpBlockedNumber readBlockedNumberFromData(BackupDataInput data) { 200a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry int id; 201a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 202a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry id = Integer.parseInt(data.getKey()); 203a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } catch (NumberFormatException e) { 204a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Log.e(TAG, "Unexpected key found in restore: " + data.getKey()); 205a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return null; 206a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 207a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 208a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 209a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry byte[] byteArray = new byte[data.getDataSize()]; 210a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry data.readEntityData(byteArray, 0, byteArray.length); 211a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry DataInputStream dataInput = new DataInputStream(new ByteArrayInputStream(byteArray)); 212a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry dataInput.readInt(); // Ignore version. 213a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BackedUpBlockedNumber blockedNumber = 214a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry new BackedUpBlockedNumber(id, readString(dataInput), readString(dataInput)); 215a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry logV("Restoring blocked number: " + blockedNumber); 216a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return blockedNumber; 217a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } catch (IOException e) { 218a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Log.e(TAG, "Error reading blocked number for: " + id + ": " + e.getMessage()); 219a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return null; 220a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 221a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 222a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 223a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private void writeToProvider(BackedUpBlockedNumber blockedNumber) { 224a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry ContentValues contentValues = new ContentValues(); 225a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry contentValues.put(BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER, 226a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry blockedNumber.originalNumber); 227a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry contentValues.put(BlockedNumberContract.BlockedNumbers.COLUMN_E164_NUMBER, 228a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry blockedNumber.e164Number); 229a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry try { 230a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry getContentResolver().insert( 231a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BlockedNumberContract.BlockedNumbers.CONTENT_URI, contentValues); 232a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } catch (Exception e) { 233a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Log.e(TAG, "Unable to insert blocked number " + blockedNumber + " :" + e.getMessage()); 234a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 235a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 236a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 237a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static boolean isDebug() { 238a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return Log.isLoggable(TAG, Log.DEBUG); 239a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 240a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 241a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static void logV(String msg) { 242a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (DEBUG) { 243a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry Log.v(TAG, msg); 244a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 245a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 246a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 247a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static class BackupState { 248a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final int version; 249a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final SortedSet<Integer> ids; 250a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 251a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BackupState(int version, SortedSet<Integer> ids) { 252a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry this.version = version; 253a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry this.ids = ids; 254a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 255a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 256a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 257a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry private static class BackedUpBlockedNumber { 258a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final int id; 259a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final String originalNumber; 260a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry final String e164Number; 261a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 262a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry BackedUpBlockedNumber(int id, String originalNumber, String e164Number) { 263a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry this.id = id; 264a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry this.originalNumber = originalNumber; 265a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry this.e164Number = e164Number; 266a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 267a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry 268a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry @Override 269a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry public String toString() { 270a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry if (isDebug()) { 271a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return String.format("[%d, original number: %s, e164 number: %s]", 272a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry id, originalNumber, e164Number); 273a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } else { 274a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry return String.format("[%d]", id); 275a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 276a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 277a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry } 278a227395c0b0d852f4a51629c85f9f35edf140496Abhijith Shastry} 279