summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/backup
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2017-08-31 06:57:16 -0700
committerEric Erfanian <erfanian@google.com>2017-08-31 16:13:53 +0000
commit2ca4318cc1ee57dda907ba2069bd61d162b1baef (patch)
treee282668a9587cf6c1ec7b604dea860400c75c6c7 /java/com/android/dialer/backup
parent68038172793ee0e2ab3e2e56ddfbeb82879d1f58 (diff)
Update Dialer source to latest internal Google revision.
Previously, Android's Dialer app was developed in an internal Google source control system and only exported to public during AOSP drops. The Dialer team is now switching to a public development model similar to the telephony team. This CL represents all internal Google changes that were committed to Dialer between the public O release and today's tip of tree on internal master. This CL squashes those changes into a single commit. In subsequent changes, changes will be exported on a per-commit basis. Test: make, flash install, run Merged-In: I45270eaa8ce732d71a1bd84b08c7fa0e99af3160 Change-Id: I529aaeb88535b9533c0ae4ef4e6c1222d4e0f1c8 PiperOrigin-RevId: 167068436
Diffstat (limited to 'java/com/android/dialer/backup')
-rw-r--r--java/com/android/dialer/backup/AndroidManifest.xml19
-rw-r--r--java/com/android/dialer/backup/DialerBackupAgent.java281
-rw-r--r--java/com/android/dialer/backup/DialerBackupUtils.java363
-rw-r--r--java/com/android/dialer/backup/DialerPersistentBackupAgent.java91
-rw-r--r--java/com/android/dialer/backup/proto/voicemail_info.proto30
5 files changed, 100 insertions, 684 deletions
diff --git a/java/com/android/dialer/backup/AndroidManifest.xml b/java/com/android/dialer/backup/AndroidManifest.xml
index 1cbbe5339..84992c0ee 100644
--- a/java/com/android/dialer/backup/AndroidManifest.xml
+++ b/java/com/android/dialer/backup/AndroidManifest.xml
@@ -1,5 +1,5 @@
<!--
- ~ Copyright (C) 2016 The Android Open Source Project
+ ~ Copyright (C) 2017 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -13,14 +13,13 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.dialer.backup">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.dialer.backup">
- <application
- android:backupAgent="com.android.dialer.backup.DialerBackupAgent"
- android:fullBackupOnly="true"
- android:restoreAnyVersion="true"
- />
-</manifest>
+ <!-- Android backup service key -->
+ <!-- https://developer.android.com/google/backup/signup.html -->
+ <meta-data
+ android:name="com.google.android.backup.api_key"
+ android:value="AEdPqrEAAAAIn3-Y3JKit1mrzfvcdbVhUiJn2ICtKfhGYLy0Bg"/>
+</manifest> \ No newline at end of file
diff --git a/java/com/android/dialer/backup/DialerBackupAgent.java b/java/com/android/dialer/backup/DialerBackupAgent.java
deleted file mode 100644
index dec1ca1a7..000000000
--- a/java/com/android/dialer/backup/DialerBackupAgent.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dialer.backup;
-
-import android.annotation.TargetApi;
-import android.app.backup.BackupAgent;
-import android.app.backup.BackupDataInput;
-import android.app.backup.BackupDataOutput;
-import android.app.backup.FullBackupDataOutput;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Build.VERSION_CODES;
-import android.os.ParcelFileDescriptor;
-import android.provider.CallLog;
-import android.provider.CallLog.Calls;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Voicemails;
-import android.telecom.PhoneAccountHandle;
-import android.util.Pair;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.ConfigProviderBindings;
-import com.android.dialer.common.LogUtil;
-import com.android.dialer.logging.DialerImpression;
-import com.android.dialer.logging.Logger;
-import com.android.dialer.telecom.TelecomUtil;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * The Dialer backup agent to backup voicemails, and files under files, shared prefs and databases
- */
-public class DialerBackupAgent extends BackupAgent {
- // File names suffix for backup/restore.
- private static final String VOICEMAIL_BACKUP_FILE_SUFFIX = "_voicemail_backup.proto";
- // File name formats for backup. It looks like 000000_voicemail_backup.proto, 0000001...
- private static final String VOICEMAIL_BACKUP_FILE_FORMAT = "%06d" + VOICEMAIL_BACKUP_FILE_SUFFIX;
- // Order by Date entries from database. We start backup from the newest.
- private static final String ORDER_BY_DATE = "date DESC";
- // Voicemail Uri Column
- public static final String VOICEMAIL_URI = "voicemail_uri";
- // Voicemail packages to backup
- public static final String VOICEMAIL_SOURCE_PACKAGE = "com.google.android.dialer";
-
- private long voicemailsBackedupSoFar = 0;
- private long sizeOfVoicemailsBackedupSoFar = 0;
- private boolean maxVoicemailBackupReached = false;
-
- /**
- * onBackup is used for Key/Value backup. Since we are using Dolly/Android Auto backup, we do not
- * need to implement this method and Dolly should not be calling this. Instead Dolly will be
- * calling onFullBackup.
- */
- @Override
- public void onBackup(
- ParcelFileDescriptor parcelFileDescriptor,
- BackupDataOutput backupDataOutput,
- ParcelFileDescriptor parcelFileDescriptor1)
- throws IOException {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_BACKUP);
- Assert.fail("Android Backup should not call DialerBackupAgent.onBackup");
- }
-
- /**
- * onRestore is used for Key/Value restore. Since we are using Dolly/Android Auto backup/restore,
- * we need to implement this method only for backwards compatibility. Dolly should be calling
- * onFileRestore during its restore.
- */
- @Override
- public void onRestore(
- BackupDataInput backupDataInput, int i, ParcelFileDescriptor parcelFileDescriptor)
- throws IOException {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_RESTORE);
- }
-
- @TargetApi(VERSION_CODES.M)
- @Override
- public void onFullBackup(FullBackupDataOutput data) throws IOException {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_FULL_BACKUP);
- LogUtil.i("DialerBackupAgent.onFullBackup", "performing dialer backup");
- boolean autoBackupEnabled =
- ConfigProviderBindings.get(this).getBoolean("enable_autobackup", true);
- boolean vmBackupEnabled = ConfigProviderBindings.get(this).getBoolean("enable_vm_backup", true);
- List<PhoneAccountHandle> phoneAccountsToArchive =
- DialerBackupUtils.getPhoneAccountsToArchive(this);
-
- if (autoBackupEnabled) {
- if (!maxVoicemailBackupReached && vmBackupEnabled && !phoneAccountsToArchive.isEmpty()) {
- voicemailsBackedupSoFar = 0;
- sizeOfVoicemailsBackedupSoFar = 0;
-
- LogUtil.i("DialerBackupAgent.onFullBackup", "autoBackup is enabled");
- ContentResolver contentResolver = getContentResolver();
- int limit = 1000;
-
- Uri uri =
- TelecomUtil.getCallLogUri(this)
- .buildUpon()
- .appendQueryParameter(Calls.LIMIT_PARAM_KEY, Integer.toString(limit))
- .build();
-
- LogUtil.i("DialerBackupAgent.onFullBackup", "backing up from: " + uri);
-
- try (Cursor cursor =
- contentResolver.query(
- uri,
- null,
- String.format(
- "(%s = ? AND deleted = 0 AND %s = ? AND ?)",
- Calls.TYPE, Voicemails.SOURCE_PACKAGE),
- new String[] {
- Integer.toString(CallLog.Calls.VOICEMAIL_TYPE),
- VOICEMAIL_SOURCE_PACKAGE,
- DialerBackupUtils.getPhoneAccountClause(phoneAccountsToArchive)
- },
- ORDER_BY_DATE,
- null)) {
-
- if (cursor == null) {
- LogUtil.i("DialerBackupAgent.onFullBackup", "cursor was null");
- return;
- }
-
- LogUtil.i("DialerBackupAgent.onFullBackup", "cursor count: " + cursor.getCount());
- if (cursor.moveToFirst()) {
- int fileNum = 0;
- do {
- backupRow(
- data, cursor, String.format(Locale.US, VOICEMAIL_BACKUP_FILE_FORMAT, fileNum++));
- } while (cursor.moveToNext() && !maxVoicemailBackupReached);
- } else {
- LogUtil.i("DialerBackupAgent.onFullBackup", "cursor.moveToFirst failed");
- }
- }
- }
- LogUtil.i(
- "DialerBackupAgent.onFullBackup",
- "vm files backed up: %d, vm size backed up:%d, "
- + "max vm backup reached:%b, vm backup enabled:%b phone accounts to archive: %d",
- voicemailsBackedupSoFar,
- sizeOfVoicemailsBackedupSoFar,
- maxVoicemailBackupReached,
- vmBackupEnabled,
- phoneAccountsToArchive.size());
- super.onFullBackup(data);
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_FULL_BACKED_UP);
- } else {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_BACKUP_DISABLED);
- LogUtil.i("DialerBackupAgent.onFullBackup", "autoBackup is disabled");
- }
- }
-
- private void backupRow(FullBackupDataOutput data, Cursor cursor, String fileName)
- throws IOException {
-
- VoicemailInfo cursorRowInProto =
- DialerBackupUtils.convertVoicemailCursorRowToProto(cursor, getContentResolver());
-
- File file = new File(getFilesDir(), fileName);
- DialerBackupUtils.writeProtoToFile(file, cursorRowInProto);
-
- if (sizeOfVoicemailsBackedupSoFar + file.length()
- > DialerBackupUtils.maxVoicemailSizeToBackup) {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_MAX_VM_BACKUP_REACHED);
- maxVoicemailBackupReached = true;
- file.delete();
- return;
- }
-
- backupFile(file, data);
- }
-
- // TODO: Write to FullBackupDataOutput directly (b/33849960)
- private void backupFile(File file, FullBackupDataOutput data) throws IOException {
- try {
- super.fullBackupFile(file, data);
- sizeOfVoicemailsBackedupSoFar = sizeOfVoicemailsBackedupSoFar + file.length();
- voicemailsBackedupSoFar++;
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_VOICEMAIL_BACKED_UP);
- LogUtil.i("DialerBackupAgent.backupFile", "file backed up:" + file.getAbsolutePath());
- } finally {
- file.delete();
- }
- }
-
- // Being tracked in b/33839952
- @Override
- public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_QUOTA_EXCEEDED);
- LogUtil.i("DialerBackupAgent.onQuotaExceeded", "does nothing");
- }
-
- @TargetApi(VERSION_CODES.M)
- @Override
- public void onRestoreFile(
- ParcelFileDescriptor data, long size, File destination, int type, long mode, long mtime)
- throws IOException {
- LogUtil.i("DialerBackupAgent.onRestoreFile", "size:" + size + " destination: " + destination);
-
- String fileName = destination.getName();
- LogUtil.i("DialerBackupAgent.onRestoreFile", "file name: " + fileName);
-
- if (ConfigProviderBindings.get(this).getBoolean("enable_autobackup", true)) {
- if (fileName.endsWith(VOICEMAIL_BACKUP_FILE_SUFFIX)
- && ConfigProviderBindings.get(this).getBoolean("enable_vm_restore", true)) {
- if (DialerBackupUtils.canRestoreVoicemails(getContentResolver(), this)) {
- try {
- super.onRestoreFile(data, size, destination, type, mode, mtime);
- restoreVoicemail(destination);
- destination.delete();
- } catch (IOException e) {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_RESTORE_IO_EXCEPTION);
- LogUtil.e(
- "DialerBackupAgent.onRestoreFile",
- "could not restore voicemail - IOException: ",
- e);
- }
- } else {
- LogUtil.i(
- "DialerBackupAgent.onRestoreFile", "build does not support restoring voicemails");
- }
-
- } else {
- super.onRestoreFile(data, size, destination, type, mode, mtime);
- LogUtil.i("DialerBackupAgent.onRestoreFile", "restored: " + fileName);
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_RESTORED_FILE);
- }
- } else {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_RESTORE_DISABLED);
- LogUtil.i("DialerBackupAgent.onRestoreFile", "autoBackup is disabled");
- }
- }
-
- @Override
- public void onRestoreFinished() {
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_ON_RESTORE_FINISHED);
- LogUtil.i("DialerBackupAgent.onRestoreFinished", "do nothing");
- }
-
- @TargetApi(VERSION_CODES.M)
- private void restoreVoicemail(File file) throws IOException {
- Pair<ContentValues, byte[]> pair =
- DialerBackupUtils.convertVoicemailProtoFileToContentValueAndAudioBytes(
- file, getApplicationContext());
-
- if (pair == null) {
- LogUtil.i("DialerBackupAgent.restoreVoicemail", "not restoring VM due to duplicate");
- Logger.get(this)
- .logImpression(DialerImpression.Type.BACKUP_ON_RESTORE_VM_DUPLICATE_NOT_RESTORING);
- return;
- }
-
- // TODO: Uniquely identify backup agent as the creator of this voicemail b/34084298
- try (OutputStream restoreStream =
- getContentResolver()
- .openOutputStream(
- getContentResolver()
- .insert(VoicemailContract.Voicemails.CONTENT_URI, pair.first))) {
- DialerBackupUtils.copyAudioBytesToContentUri(pair.second, restoreStream);
- Logger.get(this).logImpression(DialerImpression.Type.BACKUP_RESTORED_VOICEMAIL);
- }
- }
-}
diff --git a/java/com/android/dialer/backup/DialerBackupUtils.java b/java/com/android/dialer/backup/DialerBackupUtils.java
deleted file mode 100644
index 17e82e45d..000000000
--- a/java/com/android/dialer/backup/DialerBackupUtils.java
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dialer.backup;
-
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Build.VERSION_CODES;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Voicemails;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
-import android.util.Pair;
-import com.android.dialer.common.Assert;
-import com.android.dialer.common.ConfigProviderBindings;
-import com.android.dialer.common.LogUtil;
-import com.android.voicemail.VoicemailComponent;
-import com.google.common.io.ByteStreams;
-import com.google.common.io.Files;
-import com.google.protobuf.ByteString;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Helper functions for DialerBackupAgent */
-public class DialerBackupUtils {
- // Backup voicemails up to 20MB
- static long maxVoicemailSizeToBackup = 20000000L;
- static final String RESTORED_COLUMN = "restored";
-
- private DialerBackupUtils() {}
-
- public static void copyAudioBytesToContentUri(
- @NonNull byte[] audioBytesArray, @NonNull OutputStream restoreStream) throws IOException {
- LogUtil.i("DialerBackupUtils.copyStream", "audioByteArray length: " + audioBytesArray.length);
-
- ByteArrayInputStream decodedStream = new ByteArrayInputStream(audioBytesArray);
- LogUtil.i(
- "DialerBackupUtils.copyStream", "decodedStream.available: " + decodedStream.available());
-
- ByteStreams.copy(decodedStream, restoreStream);
- }
-
- public static @Nullable ByteString audioStreamToByteString(@NonNull InputStream stream)
- throws IOException {
- if (stream.available() > 0) {
- return ByteString.readFrom(stream);
- } else {
- LogUtil.i("DialerBackupUtils.audioStreamToByteArray", "no audio stream to backup");
- }
- return ByteString.EMPTY;
- }
-
- public static void writeProtoToFile(@NonNull File file, @NonNull VoicemailInfo voicemailInfo)
- throws IOException {
- LogUtil.i(
- "DialerBackupUtils.writeProtoToFile",
- "backup " + voicemailInfo + " to " + file.getAbsolutePath());
-
- byte[] bytes = voicemailInfo.toByteArray();
- Files.write(bytes, file);
- }
-
- /** Only restore voicemails that have the restored column in calllog (NMR2+ builds) */
- @TargetApi(VERSION_CODES.M)
- public static boolean canRestoreVoicemails(ContentResolver contentResolver, Context context) {
- try (Cursor cursor = contentResolver.query(Voicemails.CONTENT_URI, null, null, null, null)) {
- // Restored column only exists in NMR2 and above builds.
- if (cursor.getColumnIndex(RESTORED_COLUMN) != -1) {
- LogUtil.i("DialerBackupUtils.canRestoreVoicemails", "Build supports restore");
- return true;
- } else {
- LogUtil.i("DialerBackupUtils.canRestoreVoicemails", "Build does not support restore");
- return false;
- }
- }
- }
-
- public static VoicemailInfo protoFileToVoicemailInfo(@NonNull File file) throws IOException {
- byte[] byteArray = Files.toByteArray(file);
- return VoicemailInfo.parseFrom(byteArray);
- }
-
- @TargetApi(VERSION_CODES.M)
- public static VoicemailInfo convertVoicemailCursorRowToProto(
- @NonNull Cursor cursor, @NonNull ContentResolver contentResolver) throws IOException {
-
- VoicemailInfo.Builder voicemailInfo = VoicemailInfo.newBuilder();
-
- for (int i = 0; i < cursor.getColumnCount(); ++i) {
- String name = cursor.getColumnName(i);
- String value = cursor.getString(i);
-
- LogUtil.i(
- "DialerBackupUtils.convertVoicemailCursorRowToProto",
- "column index: %d, column name: %s, column value: %s",
- i,
- name,
- value);
-
- switch (name) {
- case Voicemails.DATE:
- voicemailInfo.setDate(value);
- break;
- case Voicemails.DELETED:
- voicemailInfo.setDeleted(value);
- break;
- case Voicemails.DIRTY:
- voicemailInfo.setDirty(value);
- break;
- case Voicemails.DIR_TYPE:
- voicemailInfo.setDirType(value);
- break;
- case Voicemails.DURATION:
- voicemailInfo.setDuration(value);
- break;
- case Voicemails.HAS_CONTENT:
- voicemailInfo.setHasContent(value);
- break;
- case Voicemails.IS_READ:
- voicemailInfo.setIsRead(value);
- break;
- case Voicemails.ITEM_TYPE:
- voicemailInfo.setItemType(value);
- break;
- case Voicemails.LAST_MODIFIED:
- voicemailInfo.setLastModified(value);
- break;
- case Voicemails.MIME_TYPE:
- voicemailInfo.setMimeType(value);
- break;
- case Voicemails.NUMBER:
- voicemailInfo.setNumber(value);
- break;
- case Voicemails.PHONE_ACCOUNT_COMPONENT_NAME:
- voicemailInfo.setPhoneAccountComponentName(value);
- break;
- case Voicemails.PHONE_ACCOUNT_ID:
- voicemailInfo.setPhoneAccountId(value);
- break;
- case Voicemails.SOURCE_DATA:
- voicemailInfo.setSourceData(value);
- break;
- case Voicemails.SOURCE_PACKAGE:
- voicemailInfo.setSourcePackage(value);
- break;
- case Voicemails.TRANSCRIPTION:
- voicemailInfo.setTranscription(value);
- break;
- case DialerBackupAgent.VOICEMAIL_URI:
- try (InputStream audioStream = contentResolver.openInputStream(Uri.parse(value))) {
- voicemailInfo.setEncodedVoicemailKey(audioStreamToByteString(audioStream));
- }
- break;
- default:
- LogUtil.i(
- "DialerBackupUtils.convertVoicemailCursorRowToProto",
- "Not backing up column: %s, with value: %s",
- name,
- value);
- break;
- }
- }
- return voicemailInfo.build();
- }
-
- public static Pair<ContentValues, byte[]> convertVoicemailProtoFileToContentValueAndAudioBytes(
- @NonNull File file, Context context) throws IOException {
-
- VoicemailInfo voicemailInfo = DialerBackupUtils.protoFileToVoicemailInfo(file);
- LogUtil.i(
- "DialerBackupUtils.convertVoicemailProtoFileToContentValueAndEncodedAudio",
- "file name: "
- + file.getName()
- + " voicemailInfo size: "
- + voicemailInfo.getSerializedSize());
-
- if (isDuplicate(context, voicemailInfo)) {
- LogUtil.i(
- "DialerBackupUtils.convertVoicemailProtoFileToContentValueAndEncodedAudio",
- "voicemail already exists");
- return null;
- } else {
- ContentValues contentValues = new ContentValues();
-
- if (voicemailInfo.hasDate()) {
- contentValues.put(Voicemails.DATE, voicemailInfo.getDate());
- }
- if (voicemailInfo.hasDeleted()) {
- contentValues.put(Voicemails.DELETED, voicemailInfo.getDeleted());
- }
- if (!voicemailInfo.hasDirty()) {
- contentValues.put(Voicemails.DIRTY, voicemailInfo.getDirty());
- }
- if (!voicemailInfo.hasDuration()) {
- contentValues.put(Voicemails.DURATION, voicemailInfo.getDuration());
- }
- if (!voicemailInfo.hasIsRead()) {
- contentValues.put(Voicemails.IS_READ, voicemailInfo.getIsRead());
- }
- if (!voicemailInfo.hasLastModified()) {
- contentValues.put(Voicemails.LAST_MODIFIED, voicemailInfo.getLastModified());
- }
- if (!voicemailInfo.hasMimeType()) {
- contentValues.put(Voicemails.MIME_TYPE, voicemailInfo.getMimeType());
- }
- if (!voicemailInfo.hasNumber()) {
- contentValues.put(Voicemails.NUMBER, voicemailInfo.getNumber());
- }
- if (!voicemailInfo.hasPhoneAccountComponentName()) {
- contentValues.put(
- Voicemails.PHONE_ACCOUNT_COMPONENT_NAME, voicemailInfo.getPhoneAccountComponentName());
- }
- if (!voicemailInfo.hasPhoneAccountId()) {
- contentValues.put(Voicemails.PHONE_ACCOUNT_ID, voicemailInfo.getPhoneAccountId());
- }
- if (!voicemailInfo.hasSourceData()) {
- contentValues.put(Voicemails.SOURCE_DATA, voicemailInfo.getSourceData());
- }
- if (!voicemailInfo.hasSourcePackage()) {
- contentValues.put(Voicemails.SOURCE_PACKAGE, voicemailInfo.getSourcePackage());
- }
- if (!voicemailInfo.hasTranscription()) {
- contentValues.put(Voicemails.TRANSCRIPTION, voicemailInfo.getTranscription());
- }
- contentValues.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
- contentValues.put(RESTORED_COLUMN, "1");
- contentValues.put(Voicemails.SOURCE_PACKAGE, getSourcePackage(context, voicemailInfo));
-
- LogUtil.i(
- "DialerBackupUtils.convertVoicemailProtoFileToContentValueAndEncodedAudio",
- "cv: " + contentValues);
-
- return Pair.create(contentValues, voicemailInfo.getEncodedVoicemailKey().toByteArray());
- }
- }
-
- /**
- * We should be using the system package name as the source package if there is no endless VM/VM
- * archive present on the device. This is to separate pre-O (no endless VM) and O+ (endless VM)
- * devices. This ensures that the source of truth for VMs is the VM server when endless VM is not
- * enabled, and when endless VM/archived VMs is present, the source of truth for VMs is the device
- * itself.
- */
- private static String getSourcePackage(Context context, VoicemailInfo voicemailInfo) {
- if (ConfigProviderBindings.get(context)
- .getBoolean("voicemail_restore_force_system_source_package", false)) {
- LogUtil.i("DialerBackupUtils.getSourcePackage", "forcing system source package");
- return "com.android.phone";
- }
- if (ConfigProviderBindings.get(context)
- .getBoolean("voicemail_restore_check_archive_for_source_package", true)) {
- if ("1".equals(voicemailInfo.getArchived())) {
- LogUtil.i(
- "DialerBackupUtils.getSourcePackage",
- "voicemail was archived, using app source package");
- // Using our app's source package will prevent the archived voicemail from being deleted by
- // the system when it syncs with the voicemail server. In most cases the user will not see
- // duplicate voicemails because this voicemail was archived and likely deleted from the
- // voicemail server.
- return context.getPackageName();
- } else {
- // Use the system source package. This means that if the voicemail is not present on the
- // voicemail server then the system will delete it when it syncs.
- LogUtil.i(
- "DialerBackupUtils.getSourcePackage",
- "voicemail was not archived, using system source package");
- return "com.android.phone";
- }
- }
- // Use our app's source package. This means that if the system syncs voicemail from the server
- // the user could potentially get duplicate voicemails.
- LogUtil.i("DialerBackupUtils.getSourcePackage", "defaulting to using app source package");
- return context.getPackageName();
- }
-
- @TargetApi(VERSION_CODES.M)
- private static boolean isDuplicate(Context context, VoicemailInfo voicemailInfo) {
- // This checks for VM that might already exist, and doesn't restore them
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(
- VoicemailContract.Voicemails.CONTENT_URI,
- null,
- String.format(
- "(%s = ? AND %s = ? AND %s = ?)",
- Voicemails.NUMBER, Voicemails.DATE, Voicemails.DURATION),
- new String[] {
- voicemailInfo.getNumber(), voicemailInfo.getDate(), voicemailInfo.getDuration()
- },
- null,
- null)) {
- if (cursor.moveToFirst()
- && ConfigProviderBindings.get(context)
- .getBoolean("enable_vm_restore_no_duplicate", true)) {
- return true;
- }
- }
- return false;
- }
-
- public static String getPhoneAccountClause(List<PhoneAccountHandle> phoneAccountsToArchive) {
- Assert.checkArgument(!phoneAccountsToArchive.isEmpty());
- StringBuilder whereQuery = new StringBuilder();
-
- whereQuery.append("(");
-
- for (int i = 0; i < phoneAccountsToArchive.size(); i++) {
- whereQuery.append(
- Voicemails.PHONE_ACCOUNT_ID + " = " + phoneAccountsToArchive.get(i).getId());
-
- if (phoneAccountsToArchive.size() > 1 && i < phoneAccountsToArchive.size() - 1) {
- whereQuery.append(" OR ");
- }
- }
- whereQuery.append(")");
- return whereQuery.toString();
- }
-
- public static List<PhoneAccountHandle> getPhoneAccountsToArchive(Context context) {
- List<PhoneAccountHandle> phoneAccountsToBackUp = new ArrayList<>();
-
- for (PhoneAccountHandle handle :
- context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts()) {
-
- if (VoicemailComponent.get(context)
- .getVoicemailClient()
- .isVoicemailArchiveEnabled(context, handle)) {
- phoneAccountsToBackUp.add(handle);
- LogUtil.i(
- "DialerBackupUtils.getPhoneAccountsToArchive", "enabled for: " + handle.toString());
- } else {
- LogUtil.i(
- "DialerBackupUtils.getPhoneAccountsToArchive", "not enabled for: " + handle.toString());
- }
- }
- return phoneAccountsToBackUp;
- }
-}
diff --git a/java/com/android/dialer/backup/DialerPersistentBackupAgent.java b/java/com/android/dialer/backup/DialerPersistentBackupAgent.java
new file mode 100644
index 000000000..18cb084c2
--- /dev/null
+++ b/java/com/android/dialer/backup/DialerPersistentBackupAgent.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.dialer.backup;
+
+import android.app.backup.BackupDataInput;
+import android.app.backup.BackupDataOutput;
+import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.util.ArrayMap;
+import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.logging.DialerImpression;
+import com.android.dialer.logging.Logger;
+import com.google.android.libraries.backup.BackupKeyPredicate;
+import com.google.android.libraries.backup.BackupKeyPredicates;
+import com.google.android.libraries.backup.PersistentBackupAgentHelper;
+import java.io.IOException;
+import java.util.Map;
+
+/** Implementation of Key/Value Backup that powers Dialer's backup and restore. */
+public class DialerPersistentBackupAgent extends PersistentBackupAgentHelper {
+
+ private static final String[] BACKUP_NAMED_SHARED_PREFS = {
+ "com.google.android.dialer_preferences", "com.google.android.dialer", "com.android.dialer"
+ };
+
+ @NonNull private final String[] sharedPreferencesToBackup;
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ DialerPersistentBackupAgent(@NonNull String[] sharedPrefs) {
+ this.sharedPreferencesToBackup = Assert.isNotNull(sharedPrefs);
+ Logger.get(this).logImpression(DialerImpression.Type.BACKUP_KEY_VALUE_BACKUP_AGENT_CONSTRUCTOR);
+ }
+
+ public DialerPersistentBackupAgent() {
+ this(BACKUP_NAMED_SHARED_PREFS);
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor stateFile)
+ throws IOException {
+ Logger.get(this).logImpression(DialerImpression.Type.BACKUP_KEY_VALUE_ON_RESTORE);
+ LogUtil.i("DialerPersistentBackupAgent.onRestore", "restore from version: " + appVersionCode);
+ super.onRestore(data, appVersionCode, stateFile);
+ }
+
+ @Override
+ public void onBackup(
+ ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState)
+ throws IOException {
+ Logger.get(this).logImpression(DialerImpression.Type.BACKUP_KEY_VALUE_ON_BACKUP);
+ LogUtil.i("DialerPersistentBackupAgent.onBackup", "onBackup being performed");
+ super.onBackup(oldState, data, newState);
+ }
+
+ @Override
+ public Map<String, BackupKeyPredicate> getBackupSpecification() {
+ Logger.get(this).logImpression(DialerImpression.Type.BACKUP_KEY_VALUE_GET_BACKUP_SPECIFICATION);
+ LogUtil.i(
+ "DialerPersistentBackupAgent.getBackupSpecification",
+ "number of files being backed up: " + sharedPreferencesToBackup.length);
+
+ Map<String, BackupKeyPredicate> arrayMap = new ArrayMap<>();
+ for (String fileName : sharedPreferencesToBackup) {
+ LogUtil.i("DialerPersistentBackupAgent.getBackupSpecification", "arrayMap.put: " + fileName);
+ arrayMap.put(fileName, BackupKeyPredicates.alwaysTrue());
+ }
+
+ return arrayMap;
+ }
+
+ @Override
+ public void onRestoreFinished() {
+ Logger.get(this).logImpression(DialerImpression.Type.BACKUP_KEY_VALUE_ON_RESTORE_FINISHED);
+ super.onRestoreFinished();
+ }
+}
diff --git a/java/com/android/dialer/backup/proto/voicemail_info.proto b/java/com/android/dialer/backup/proto/voicemail_info.proto
deleted file mode 100644
index b74cce954..000000000
--- a/java/com/android/dialer/backup/proto/voicemail_info.proto
+++ /dev/null
@@ -1,30 +0,0 @@
-syntax = "proto2";
-
-option java_package = "com.android.dialer.backup";
-option java_multiple_files = true;
-option optimize_for = LITE_RUNTIME;
-
-package com.android.dialer.backup;
-
-// Next id: 20
-message VoicemailInfo {
- optional string date = 1;
- optional string deleted = 2;
- optional string dirty = 3;
- optional string dir_type = 4;
- optional string duration = 5;
- optional string has_content = 6;
- optional string is_read = 7;
- optional string item_type = 8;
- optional string last_modified = 9;
- optional string mime_type = 10;
- optional string number = 11;
- optional string phone_account_component_name = 12;
- optional string phone_account_id = 13;
- optional string source_data = 14;
- optional string source_package = 15;
- optional string transcription = 16;
- optional string voicemail_uri = 17;
- optional bytes encoded_voicemail_key = 18;
- optional string archived = 19;
-}