diff options
author | Xin Li <delphij@google.com> | 2023-08-22 11:37:02 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2023-08-22 11:37:02 -0700 |
commit | 4e1da335389dfa3a45909f23a168d9005038f07c (patch) | |
tree | 506bacf36a34cc31bef5f09829b1344f5cc899f3 | |
parent | a7901d5731807a4a48d06b444e79c3258a2b4c9b (diff) | |
parent | d9b5b6bd0e8d1957ffd2d6ba302af89d57c34683 (diff) | |
download | CallLogProvider-tmp_amf_298295554.tar.gz |
Merge Android U (ab/10368041)tmp_amf_298295554
Bug: 291102124
Merged-In: Ifd3de30954ef544a35af280d002e6b239b7ba329
Change-Id: I7b3f40d111edf7ca2183396f0803e834bab39926
-rw-r--r-- | src/com/android/calllogbackup/CallLogBackupAgent.java | 82 | ||||
-rw-r--r-- | tests/src/com/android/calllogbackup/CallLogBackupAgentTest.java | 79 |
2 files changed, 160 insertions, 1 deletions
diff --git a/src/com/android/calllogbackup/CallLogBackupAgent.java b/src/com/android/calllogbackup/CallLogBackupAgent.java index 8b58f99..4bb55b0 100644 --- a/src/com/android/calllogbackup/CallLogBackupAgent.java +++ b/src/com/android/calllogbackup/CallLogBackupAgent.java @@ -21,6 +21,8 @@ import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED; import android.app.backup.BackupAgent; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; +import android.app.backup.BackupManager; +import android.app.backup.BackupRestoreEventLogger; import android.content.ComponentName; import android.content.ContentResolver; import android.database.Cursor; @@ -108,6 +110,22 @@ public class CallLogBackupAgent extends BackupAgent { private static final String TAG = "CallLogBackupAgent"; + /** Data types and errors used when reporting B&R success rate and errors. */ + @BackupRestoreEventLogger.BackupRestoreDataType + @VisibleForTesting + static final String CALLLOGS = "telecom_call_logs"; + + @BackupRestoreEventLogger.BackupRestoreError + static final String ERROR_UNEXPECTED_KEY = "unexpected_key"; + @BackupRestoreEventLogger.BackupRestoreError + static final String ERROR_END_OEM_MARKER_NOT_FOUND = "end_oem_marker_not_found"; + @BackupRestoreEventLogger.BackupRestoreError + static final String ERROR_READING_CALL_DATA = "error_reading_call_data"; + @BackupRestoreEventLogger.BackupRestoreError + static final String ERROR_BACKUP_CALL_FAILED = "backup_call_failed"; + + private BackupRestoreEventLogger mLogger; + /** Current version of CallLogBackup. Used to track the backup format. */ @VisibleForTesting static final int VERSION = 1009; @@ -151,6 +169,56 @@ public class CallLogBackupAgent extends BackupAgent { CallLog.Calls.IS_PHONE_ACCOUNT_MIGRATION_PENDING }; + /** + * BackupRestoreEventLogger Dependencies for testing. + */ + @VisibleForTesting + public interface BackupRestoreEventLoggerProxy { + void logItemsBackedUp(String dataType, int count); + void logItemsBackupFailed(String dataType, int count, String error); + void logItemsRestored(String dataType, int count); + void logItemsRestoreFailed(String dataType, int count, String error); + } + + private BackupRestoreEventLoggerProxy mBackupRestoreEventLoggerProxy = + new BackupRestoreEventLoggerProxy() { + @Override + public void logItemsBackedUp(String dataType, int count) { + mLogger.logItemsBackedUp(dataType, count); + } + + @Override + public void logItemsBackupFailed(String dataType, int count, String error) { + mLogger.logItemsBackupFailed(dataType, count, error); + } + + @Override + public void logItemsRestored(String dataType, int count) { + mLogger.logItemsRestored(dataType, count); + } + + @Override + public void logItemsRestoreFailed(String dataType, int count, String error) { + mLogger.logItemsRestoreFailed(dataType, count, error); + } + }; + + /** + * Overrides BackupRestoreEventLogger dependencies for testing. + */ + @VisibleForTesting + public void setBackupRestoreEventLoggerProxy(BackupRestoreEventLoggerProxy proxy) { + mBackupRestoreEventLoggerProxy = proxy; + } + + @Override + public void onCreate() { + super.onCreate(); + Log.d(TAG, "onCreate"); + BackupManager backupManager = new BackupManager(getApplicationContext()); + mLogger = backupManager.getBackupRestoreEventLogger(/* backupAgent */ this); + } + /** ${inheritDoc} */ @Override public void onBackup(ParcelFileDescriptor oldStateDescriptor, BackupDataOutput data, @@ -205,6 +273,7 @@ public class CallLogBackupAgent extends BackupAgent { Call call = readCallFromData(data); if (call != null && call.type != Calls.VOICEMAIL_TYPE) { writeCallToProvider(call); + mBackupRestoreEventLoggerProxy.logItemsRestored(CALLLOGS, /* count */ 1); if (isDebug()) { Log.d(TAG, "Restored call: " + call); } @@ -233,6 +302,7 @@ public class CallLogBackupAgent extends BackupAgent { // This call still exists in the current call log so delete it from the // "callsToRemove" set since we want to keep it. callsToRemove.remove(call.id); + mBackupRestoreEventLoggerProxy.logItemsBackedUp(CALLLOGS, /* count */ 1); } } @@ -339,6 +409,8 @@ public class CallLogBackupAgent extends BackupAgent { try { callId = Integer.parseInt(data.getKey()); } catch (NumberFormatException e) { + mBackupRestoreEventLoggerProxy.logItemsRestoreFailed( + CALLLOGS, /* count */ 1, ERROR_UNEXPECTED_KEY); Log.e(TAG, "Unexpected key found in restore: " + data.getKey()); return null; } @@ -374,6 +446,8 @@ public class CallLogBackupAgent extends BackupAgent { int marker = dataInput.readInt(); if (marker != END_OEM_DATA_MARKER) { + mBackupRestoreEventLoggerProxy.logItemsRestoreFailed(CALLLOGS, /* count */ 1, + ERROR_END_OEM_MARKER_NOT_FOUND); Log.e(TAG, "Did not find END-OEM marker for call " + call.id); // The marker does not match the expected value, ignore this call completely. return null; @@ -432,6 +506,8 @@ public class CallLogBackupAgent extends BackupAgent { } return call; } catch (IOException e) { + mBackupRestoreEventLoggerProxy.logItemsRestoreFailed( + CALLLOGS, /* count */ 1, ERROR_READING_CALL_DATA); Log.e(TAG, "Error reading call data for " + callId, e); return null; } @@ -566,10 +642,14 @@ public class CallLogBackupAgent extends BackupAgent { output.writeEntityHeader(Integer.toString(call.id), baos.size()); output.writeEntityData(baos.toByteArray(), baos.size()); + mBackupRestoreEventLoggerProxy.logItemsBackedUp(CALLLOGS, /* count */ 1); + if (isDebug()) { Log.d(TAG, "Wrote call to backup: " + call + " with byte array: " + baos); } - } catch (IOException e) { + } catch (Exception e) { + mBackupRestoreEventLoggerProxy.logItemsBackupFailed( + CALLLOGS, /* count */ 1, ERROR_BACKUP_CALL_FAILED); Log.e(TAG, "Failed to backup call: " + call, e); } } diff --git a/tests/src/com/android/calllogbackup/CallLogBackupAgentTest.java b/tests/src/com/android/calllogbackup/CallLogBackupAgentTest.java index 4567e40..de681e5 100644 --- a/tests/src/com/android/calllogbackup/CallLogBackupAgentTest.java +++ b/tests/src/com/android/calllogbackup/CallLogBackupAgentTest.java @@ -16,6 +16,8 @@ package com.android.calllogbackup; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.Mockito.eq; @@ -41,6 +43,7 @@ import org.mockito.MockitoAnnotations; import java.io.DataInput; import java.io.DataOutput; import java.io.EOFException; +import java.io.IOException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -57,11 +60,38 @@ public class CallLogBackupAgentTest extends AndroidTestCase { static final String TEST_PHONE_ACCOUNT_HANDLE_SUB_ID = "666"; static final int TEST_PHONE_ACCOUNT_HANDLE_SUB_ID_INT = 666; static final String TEST_PHONE_ACCOUNT_HANDLE_ICC_ID = "891004234814455936F"; + + public int backupRestoreLoggerSuccessCount = 0; + public int backupRestoreLoggerFailCount = 0; + @Mock DataInput mDataInput; @Mock DataOutput mDataOutput; @Mock BackupDataOutput mBackupDataOutput; @Mock Cursor mCursor; + private CallLogBackupAgent.BackupRestoreEventLoggerProxy mBackupRestoreEventLoggerProxy = + new CallLogBackupAgent.BackupRestoreEventLoggerProxy() { + @Override + public void logItemsBackedUp(String dataType, int count) { + backupRestoreLoggerSuccessCount += count; + } + + @Override + public void logItemsBackupFailed(String dataType, int count, String error) { + backupRestoreLoggerFailCount += count; + } + + @Override + public void logItemsRestored(String dataType, int count) { + backupRestoreLoggerSuccessCount += count; + } + + @Override + public void logItemsRestoreFailed(String dataType, int count, String error) { + backupRestoreLoggerFailCount += count; + } + }; + CallLogBackupAgent mCallLogBackupAgent; MockitoHelper mMockitoHelper = new MockitoHelper(); @@ -77,6 +107,7 @@ public class CallLogBackupAgentTest extends AndroidTestCase { MockitoAnnotations.initMocks(this); mCallLogBackupAgent = new CallLogBackupAgent(); + mCallLogBackupAgent.setBackupRestoreEventLoggerProxy(mBackupRestoreEventLoggerProxy); } @Override @@ -178,9 +209,45 @@ public class CallLogBackupAgentTest extends AndroidTestCase { mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); + // Ensure the {@link BackupRestoreEventLogger} is not notified as no calls were backed up: + assertEquals(backupRestoreLoggerSuccessCount, 0); + assertEquals(backupRestoreLoggerFailCount, 0); + Mockito.verifyNoMoreInteractions(mBackupDataOutput); } + public void testRunBackup_OneNewCall_ErrorAddingCall() throws Exception { + CallLogBackupState state = new CallLogBackupState(); + state.version = CallLogBackupAgent.VERSION; + state.callIds = new TreeSet<>(); + List<Call> calls = new LinkedList<>(); + calls.add(makeCall(101, 0L, 0L, "555-5555")); + + // Throw an exception when the call is added to the backup: + when(mBackupDataOutput.writeEntityData(any(byte[].class), anyInt())) + .thenThrow(IOException.class); + mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); + + // Ensure the {@link BackupRestoreEventLogger} is informed of the failed backed up call: + assertEquals(backupRestoreLoggerSuccessCount, 0); + assertEquals(backupRestoreLoggerFailCount, 1); + } + + public void testRunBackup_OneNewCall_NullBackupDataOutput() throws Exception { + CallLogBackupState state = new CallLogBackupState(); + state.version = CallLogBackupAgent.VERSION; + state.callIds = new TreeSet<>(); + List<Call> calls = new LinkedList<>(); + calls.add(makeCall(101, 0L, 0L, "555-5555")); + + // Invoke runBackup() with a null value for BackupDataOutput causing an exception: + mCallLogBackupAgent.runBackup(state, null, calls); + + // Ensure the {@link BackupRestoreEventLogger} is informed of the failed backed up call: + assertEquals(backupRestoreLoggerSuccessCount, 0); + assertEquals(backupRestoreLoggerFailCount, 1); + } + public void testRunBackup_OneNewCall() throws Exception { CallLogBackupState state = new CallLogBackupState(); state.version = CallLogBackupAgent.VERSION; @@ -189,6 +256,10 @@ public class CallLogBackupAgentTest extends AndroidTestCase { calls.add(makeCall(101, 0L, 0L, "555-5555")); mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); + // Ensure the {@link BackupRestoreEventLogger} is informed of the backed up call: + assertEquals(backupRestoreLoggerSuccessCount, 1); + assertEquals(backupRestoreLoggerFailCount, 0); + verify(mBackupDataOutput).writeEntityHeader(eq("101"), Matchers.anyInt()); verify(mBackupDataOutput).writeEntityData((byte[]) Matchers.any(), Matchers.anyInt()); } @@ -274,6 +345,10 @@ public class CallLogBackupAgentTest extends AndroidTestCase { mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); + // Ensure the {@link BackupRestoreEventLogger} is informed of the 2 backed up calls: + assertEquals(backupRestoreLoggerSuccessCount, 2); + assertEquals(backupRestoreLoggerFailCount, 0); + InOrder inOrder = Mockito.inOrder(mBackupDataOutput); inOrder.verify(mBackupDataOutput).writeEntityHeader(eq("101"), Matchers.anyInt()); inOrder.verify(mBackupDataOutput). @@ -296,6 +371,10 @@ public class CallLogBackupAgentTest extends AndroidTestCase { mCallLogBackupAgent.runBackup(state, mBackupDataOutput, calls); + // Ensure the {@link BackupRestoreEventLogger} is informed of the 2 backed up calls: + assertEquals(backupRestoreLoggerSuccessCount, 2); + assertEquals(backupRestoreLoggerFailCount, 0); + InOrder inOrder = Mockito.inOrder(mBackupDataOutput); inOrder.verify(mBackupDataOutput).writeEntityHeader(eq("102"), Matchers.anyInt()); inOrder.verify(mBackupDataOutput). |