Loading services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +5 −29 Original line number Original line Diff line number Diff line Loading @@ -84,14 +84,12 @@ public class NotificationHistoryDatabase { // Current version of the database files schema // Current version of the database files schema private int mCurrentVersion; private int mCurrentVersion; private final WriteBufferRunnable mWriteBufferRunnable; private final WriteBufferRunnable mWriteBufferRunnable; private final FileAttrProvider mFileAttrProvider; // Object containing posted notifications that have not yet been written to disk // Object containing posted notifications that have not yet been written to disk @VisibleForTesting @VisibleForTesting NotificationHistory mBuffer; NotificationHistory mBuffer; public NotificationHistoryDatabase(Context context, Handler fileWriteHandler, File dir, public NotificationHistoryDatabase(Context context, Handler fileWriteHandler, File dir) { FileAttrProvider fileAttrProvider) { mContext = context; mContext = context; mAlarmManager = context.getSystemService(AlarmManager.class); mAlarmManager = context.getSystemService(AlarmManager.class); mCurrentVersion = DEFAULT_CURRENT_VERSION; mCurrentVersion = DEFAULT_CURRENT_VERSION; Loading @@ -101,7 +99,6 @@ public class NotificationHistoryDatabase { mHistoryFiles = new LinkedList<>(); mHistoryFiles = new LinkedList<>(); mBuffer = new NotificationHistory(); mBuffer = new NotificationHistory(); mWriteBufferRunnable = new WriteBufferRunnable(); mWriteBufferRunnable = new WriteBufferRunnable(); mFileAttrProvider = fileAttrProvider; IntentFilter deletionFilter = new IntentFilter(ACTION_HISTORY_DELETION); IntentFilter deletionFilter = new IntentFilter(ACTION_HISTORY_DELETION); deletionFilter.addDataScheme(SCHEME_DELETION); deletionFilter.addDataScheme(SCHEME_DELETION); Loading Loading @@ -131,8 +128,8 @@ public class NotificationHistoryDatabase { } } // Sort with newest files first // Sort with newest files first Arrays.sort(files, (lhs, rhs) -> Long.compare(mFileAttrProvider.getCreationTime(rhs), Arrays.sort(files, (lhs, rhs) -> Long.compare(Long.parseLong(rhs.getName()), mFileAttrProvider.getCreationTime(lhs))); Long.parseLong(lhs.getName()))); for (File file : files) { for (File file : files) { mHistoryFiles.addLast(new AtomicFile(file)); mHistoryFiles.addLast(new AtomicFile(file)); Loading Loading @@ -255,10 +252,9 @@ public class NotificationHistoryDatabase { for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { final AtomicFile currentOldestFile = mHistoryFiles.get(i); final AtomicFile currentOldestFile = mHistoryFiles.get(i); final long creationTime = final long creationTime = Long.parseLong(currentOldestFile.getBaseFile().getName()); mFileAttrProvider.getCreationTime(currentOldestFile.getBaseFile()); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Pruning " + currentOldestFile.getBaseFile().getName() Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName() + " created on " + creationTime); + " created on " + creationTime); } } if (creationTime <= retentionBoundary.getTimeInMillis()) { if (creationTime <= retentionBoundary.getTimeInMillis()) { Loading Loading @@ -469,24 +465,4 @@ public class NotificationHistoryDatabase { } } } } } } public static final class NotificationHistoryFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { final static String TAG = "NotifHistoryFileDate"; public long getCreationTime(File file) { try { BasicFileAttributes attr = Files.readAttributes(FileSystems.getDefault().getPath( file.getAbsolutePath()), BasicFileAttributes.class); return attr.creationTime().to(TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.w(TAG, "Cannot read creation data for file; using file name"); return Long.valueOf(file.getName()); } } } interface FileAttrProvider { long getCreationTime(File file); } } } services/core/java/com/android/server/notification/NotificationHistoryDatabaseFactory.java +2 −3 Original line number Original line Diff line number Diff line Loading @@ -31,11 +31,10 @@ public class NotificationHistoryDatabaseFactory { } } public static NotificationHistoryDatabase create(@NonNull Context context, public static NotificationHistoryDatabase create(@NonNull Context context, @NonNull Handler handler, @NonNull File rootDir, @NonNull Handler handler, @NonNull File rootDir) { @NonNull NotificationHistoryDatabase.FileAttrProvider fileAttrProvider) { if(sTestingNotificationHistoryDb != null) { if(sTestingNotificationHistoryDb != null) { return sTestingNotificationHistoryDb; return sTestingNotificationHistoryDb; } } return new NotificationHistoryDatabase(context, handler, rootDir, fileAttrProvider); return new NotificationHistoryDatabase(context, handler, rootDir); } } } } services/core/java/com/android/server/notification/NotificationHistoryManager.java +1 −2 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.server.IoThread; import com.android.server.IoThread; import com.android.server.notification.NotificationHistoryDatabase.NotificationHistoryFileAttrProvider; import java.io.File; import java.io.File; import java.util.ArrayList; import java.util.ArrayList; Loading Loading @@ -291,7 +290,7 @@ public class NotificationHistoryManager { final File historyDir = new File(Environment.getDataSystemCeDirectory(userId), final File historyDir = new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER); DIRECTORY_PER_USER); userHistory = NotificationHistoryDatabaseFactory.create(mContext, IoThread.getHandler(), userHistory = NotificationHistoryDatabaseFactory.create(mContext, IoThread.getHandler(), historyDir, new NotificationHistoryFileAttrProvider()); historyDir); if (mUserUnlockedStates.get(userId)) { if (mUserUnlockedStates.get(userId)) { try { try { userHistory.init(); userHistory.init(); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java +3 −15 Original line number Original line Diff line number Diff line Loading @@ -64,7 +64,6 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { Context mContext; Context mContext; @Mock @Mock AlarmManager mAlarmManager; AlarmManager mAlarmManager; TestFileAttrProvider mFileAttrProvider; NotificationHistoryDatabase mDataBase; NotificationHistoryDatabase mDataBase; Loading Loading @@ -103,11 +102,9 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { when(mContext.getUser()).thenReturn(getContext().getUser()); when(mContext.getUser()).thenReturn(getContext().getUser()); when(mContext.getPackageName()).thenReturn(getContext().getPackageName()); when(mContext.getPackageName()).thenReturn(getContext().getPackageName()); mFileAttrProvider = new TestFileAttrProvider(); mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest"); mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest"); mDataBase = new NotificationHistoryDatabase( mDataBase = new NotificationHistoryDatabase(mContext, mFileWriteHandler, mRootDir); mContext, mFileWriteHandler, mRootDir, mFileAttrProvider); mDataBase.init(); mDataBase.init(); } } Loading @@ -127,7 +124,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { // add 5 files with a creation date of "today" // add 5 files with a creation date of "today" for (long i = cal.getTimeInMillis(); i >= 5; i--) { for (long i = cal.getTimeInMillis(); i >= 5; i--) { File file = mock(File.class); File file = mock(File.class); mFileAttrProvider.creationDates.put(file, i); when(file.getName()).thenReturn(String.valueOf(i)); AtomicFile af = new AtomicFile(file); AtomicFile af = new AtomicFile(file); expectedFiles.add(af); expectedFiles.add(af); mDataBase.mHistoryFiles.addLast(af); mDataBase.mHistoryFiles.addLast(af); Loading @@ -137,7 +134,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { // Add 5 more files more than retainDays old // Add 5 more files more than retainDays old for (int i = 5; i >= 0; i--) { for (int i = 5; i >= 0; i--) { File file = mock(File.class); File file = mock(File.class); mFileAttrProvider.creationDates.put(file, cal.getTimeInMillis() - i); when(file.getName()).thenReturn(String.valueOf(cal.getTimeInMillis() - i)); AtomicFile af = new AtomicFile(file); AtomicFile af = new AtomicFile(file); mDataBase.mHistoryFiles.addLast(af); mDataBase.mHistoryFiles.addLast(af); } } Loading Loading @@ -331,13 +328,4 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { verify(nh).removeConversationFromWrite("pkg", "convo"); verify(nh).removeConversationFromWrite("pkg", "convo"); verify(af, never()).startWrite(); verify(af, never()).startWrite(); } } private class TestFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { public Map<File, Long> creationDates = new HashMap<>(); @Override public long getCreationTime(File file) { return creationDates.get(file); } } } } Loading
services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +5 −29 Original line number Original line Diff line number Diff line Loading @@ -84,14 +84,12 @@ public class NotificationHistoryDatabase { // Current version of the database files schema // Current version of the database files schema private int mCurrentVersion; private int mCurrentVersion; private final WriteBufferRunnable mWriteBufferRunnable; private final WriteBufferRunnable mWriteBufferRunnable; private final FileAttrProvider mFileAttrProvider; // Object containing posted notifications that have not yet been written to disk // Object containing posted notifications that have not yet been written to disk @VisibleForTesting @VisibleForTesting NotificationHistory mBuffer; NotificationHistory mBuffer; public NotificationHistoryDatabase(Context context, Handler fileWriteHandler, File dir, public NotificationHistoryDatabase(Context context, Handler fileWriteHandler, File dir) { FileAttrProvider fileAttrProvider) { mContext = context; mContext = context; mAlarmManager = context.getSystemService(AlarmManager.class); mAlarmManager = context.getSystemService(AlarmManager.class); mCurrentVersion = DEFAULT_CURRENT_VERSION; mCurrentVersion = DEFAULT_CURRENT_VERSION; Loading @@ -101,7 +99,6 @@ public class NotificationHistoryDatabase { mHistoryFiles = new LinkedList<>(); mHistoryFiles = new LinkedList<>(); mBuffer = new NotificationHistory(); mBuffer = new NotificationHistory(); mWriteBufferRunnable = new WriteBufferRunnable(); mWriteBufferRunnable = new WriteBufferRunnable(); mFileAttrProvider = fileAttrProvider; IntentFilter deletionFilter = new IntentFilter(ACTION_HISTORY_DELETION); IntentFilter deletionFilter = new IntentFilter(ACTION_HISTORY_DELETION); deletionFilter.addDataScheme(SCHEME_DELETION); deletionFilter.addDataScheme(SCHEME_DELETION); Loading Loading @@ -131,8 +128,8 @@ public class NotificationHistoryDatabase { } } // Sort with newest files first // Sort with newest files first Arrays.sort(files, (lhs, rhs) -> Long.compare(mFileAttrProvider.getCreationTime(rhs), Arrays.sort(files, (lhs, rhs) -> Long.compare(Long.parseLong(rhs.getName()), mFileAttrProvider.getCreationTime(lhs))); Long.parseLong(lhs.getName()))); for (File file : files) { for (File file : files) { mHistoryFiles.addLast(new AtomicFile(file)); mHistoryFiles.addLast(new AtomicFile(file)); Loading Loading @@ -255,10 +252,9 @@ public class NotificationHistoryDatabase { for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { for (int i = mHistoryFiles.size() - 1; i >= 0; i--) { final AtomicFile currentOldestFile = mHistoryFiles.get(i); final AtomicFile currentOldestFile = mHistoryFiles.get(i); final long creationTime = final long creationTime = Long.parseLong(currentOldestFile.getBaseFile().getName()); mFileAttrProvider.getCreationTime(currentOldestFile.getBaseFile()); if (DEBUG) { if (DEBUG) { Slog.d(TAG, "Pruning " + currentOldestFile.getBaseFile().getName() Slog.d(TAG, "File " + currentOldestFile.getBaseFile().getName() + " created on " + creationTime); + " created on " + creationTime); } } if (creationTime <= retentionBoundary.getTimeInMillis()) { if (creationTime <= retentionBoundary.getTimeInMillis()) { Loading Loading @@ -469,24 +465,4 @@ public class NotificationHistoryDatabase { } } } } } } public static final class NotificationHistoryFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { final static String TAG = "NotifHistoryFileDate"; public long getCreationTime(File file) { try { BasicFileAttributes attr = Files.readAttributes(FileSystems.getDefault().getPath( file.getAbsolutePath()), BasicFileAttributes.class); return attr.creationTime().to(TimeUnit.MILLISECONDS); } catch (Exception e) { Slog.w(TAG, "Cannot read creation data for file; using file name"); return Long.valueOf(file.getName()); } } } interface FileAttrProvider { long getCreationTime(File file); } } }
services/core/java/com/android/server/notification/NotificationHistoryDatabaseFactory.java +2 −3 Original line number Original line Diff line number Diff line Loading @@ -31,11 +31,10 @@ public class NotificationHistoryDatabaseFactory { } } public static NotificationHistoryDatabase create(@NonNull Context context, public static NotificationHistoryDatabase create(@NonNull Context context, @NonNull Handler handler, @NonNull File rootDir, @NonNull Handler handler, @NonNull File rootDir) { @NonNull NotificationHistoryDatabase.FileAttrProvider fileAttrProvider) { if(sTestingNotificationHistoryDb != null) { if(sTestingNotificationHistoryDb != null) { return sTestingNotificationHistoryDb; return sTestingNotificationHistoryDb; } } return new NotificationHistoryDatabase(context, handler, rootDir, fileAttrProvider); return new NotificationHistoryDatabase(context, handler, rootDir); } } } }
services/core/java/com/android/server/notification/NotificationHistoryManager.java +1 −2 Original line number Original line Diff line number Diff line Loading @@ -38,7 +38,6 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.server.IoThread; import com.android.server.IoThread; import com.android.server.notification.NotificationHistoryDatabase.NotificationHistoryFileAttrProvider; import java.io.File; import java.io.File; import java.util.ArrayList; import java.util.ArrayList; Loading Loading @@ -291,7 +290,7 @@ public class NotificationHistoryManager { final File historyDir = new File(Environment.getDataSystemCeDirectory(userId), final File historyDir = new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER); DIRECTORY_PER_USER); userHistory = NotificationHistoryDatabaseFactory.create(mContext, IoThread.getHandler(), userHistory = NotificationHistoryDatabaseFactory.create(mContext, IoThread.getHandler(), historyDir, new NotificationHistoryFileAttrProvider()); historyDir); if (mUserUnlockedStates.get(userId)) { if (mUserUnlockedStates.get(userId)) { try { try { userHistory.init(); userHistory.init(); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java +3 −15 Original line number Original line Diff line number Diff line Loading @@ -64,7 +64,6 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { Context mContext; Context mContext; @Mock @Mock AlarmManager mAlarmManager; AlarmManager mAlarmManager; TestFileAttrProvider mFileAttrProvider; NotificationHistoryDatabase mDataBase; NotificationHistoryDatabase mDataBase; Loading Loading @@ -103,11 +102,9 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { when(mContext.getUser()).thenReturn(getContext().getUser()); when(mContext.getUser()).thenReturn(getContext().getUser()); when(mContext.getPackageName()).thenReturn(getContext().getPackageName()); when(mContext.getPackageName()).thenReturn(getContext().getPackageName()); mFileAttrProvider = new TestFileAttrProvider(); mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest"); mRootDir = new File(mContext.getFilesDir(), "NotificationHistoryDatabaseTest"); mDataBase = new NotificationHistoryDatabase( mDataBase = new NotificationHistoryDatabase(mContext, mFileWriteHandler, mRootDir); mContext, mFileWriteHandler, mRootDir, mFileAttrProvider); mDataBase.init(); mDataBase.init(); } } Loading @@ -127,7 +124,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { // add 5 files with a creation date of "today" // add 5 files with a creation date of "today" for (long i = cal.getTimeInMillis(); i >= 5; i--) { for (long i = cal.getTimeInMillis(); i >= 5; i--) { File file = mock(File.class); File file = mock(File.class); mFileAttrProvider.creationDates.put(file, i); when(file.getName()).thenReturn(String.valueOf(i)); AtomicFile af = new AtomicFile(file); AtomicFile af = new AtomicFile(file); expectedFiles.add(af); expectedFiles.add(af); mDataBase.mHistoryFiles.addLast(af); mDataBase.mHistoryFiles.addLast(af); Loading @@ -137,7 +134,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { // Add 5 more files more than retainDays old // Add 5 more files more than retainDays old for (int i = 5; i >= 0; i--) { for (int i = 5; i >= 0; i--) { File file = mock(File.class); File file = mock(File.class); mFileAttrProvider.creationDates.put(file, cal.getTimeInMillis() - i); when(file.getName()).thenReturn(String.valueOf(cal.getTimeInMillis() - i)); AtomicFile af = new AtomicFile(file); AtomicFile af = new AtomicFile(file); mDataBase.mHistoryFiles.addLast(af); mDataBase.mHistoryFiles.addLast(af); } } Loading Loading @@ -331,13 +328,4 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase { verify(nh).removeConversationFromWrite("pkg", "convo"); verify(nh).removeConversationFromWrite("pkg", "convo"); verify(af, never()).startWrite(); verify(af, never()).startWrite(); } } private class TestFileAttrProvider implements NotificationHistoryDatabase.FileAttrProvider { public Map<File, Long> creationDates = new HashMap<>(); @Override public long getCreationTime(File file) { return creationDates.get(file); } } } }