Loading res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,9 @@ <!-- Whether or not TopLevelSettings should force rounded icon for injected tiles --> <bool name="config_force_rounded_icon_TopLevelSettings">true</bool> <!-- Whether dismissal timestamp should be kept before deletion --> <bool name="config_keep_contextual_card_dismissal_timestamp">false</bool> <!-- Settings intelligence package name --> <string name="config_settingsintelligence_package_name" translatable="false"> com.android.settings.intelligence Loading src/com/android/settings/homepage/contextualcards/CardContentProvider.java +45 −5 Original line number Diff line number Diff line Loading @@ -26,12 +26,16 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.os.Build; import android.os.StrictMode; import android.util.ArrayMap; import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.Map; /** * Provider stores and manages user interaction feedback for homepage contextual cards. */ Loading Loading @@ -81,6 +85,9 @@ public class CardContentProvider extends ContentProvider { final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); int numInserted = 0; final SQLiteDatabase database = mDBHelper.getWritableDatabase(); final boolean keepDismissalTimestampBeforeDeletion = getContext().getResources() .getBoolean(R.bool.config_keep_contextual_card_dismissal_timestamp); final Map<String, Long> dismissedTimeMap = new ArrayMap<>(); try { maybeEnableStrictMode(); Loading @@ -88,9 +95,42 @@ public class CardContentProvider extends ContentProvider { final String table = getTableFromMatch(uri); database.beginTransaction(); // Here deletion first is avoiding redundant insertion. According to cl/215350754 if (keepDismissalTimestampBeforeDeletion) { // Query the existing db and get dismissal info. final String[] columns = new String[]{CardDatabaseHelper.CardColumns.NAME, CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP}; final String selection = CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " IS NOT NULL"; try (Cursor cursor = database.query(table, columns, selection, null/* selectionArgs */, null /* groupBy */, null /* having */, null /* orderBy */)) { // Save them to a Map for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { final String cardName = cursor.getString(cursor.getColumnIndex( CardDatabaseHelper.CardColumns.NAME)); final long timestamp = cursor.getLong(cursor.getColumnIndex( CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP)); dismissedTimeMap.put(cardName, timestamp); } } } // Here delete data first to avoid redundant insertion. According to cl/215350754 database.delete(table, null /* whereClause */, null /* whereArgs */); for (ContentValues value : values) { if (keepDismissalTimestampBeforeDeletion) { // Replace dismissedTimestamp in each value if there is an old one. final String cardName = value.get(CardDatabaseHelper.CardColumns.NAME).toString(); if (dismissedTimeMap.containsKey(cardName)) { // Replace the value of dismissedTimestamp value.put(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP, dismissedTimeMap.get(cardName)); Log.d(TAG, "Replace dismissed time: " + cardName); } } long ret = database.insert(table, null /* nullColumnHack */, value); if (ret != -1L) { numInserted++; Loading tests/robotests/res/values-mcc999/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ <!-- Whether or not extra preview panels should be used for screen zoom setting. --> <bool name="config_enable_extra_screen_zoom_preview">false</bool> <!-- Whether dismissal timestamp should be kept before deletion --> <bool name="config_keep_contextual_card_dismissal_timestamp">true</bool> <!-- List of a11y components on the device allowed to be enabled by Settings Slices --> <string-array name="config_settings_slices_accessibility_components" translatable="false"> Loading tests/robotests/src/com/android/settings/homepage/contextualcards/CardContentProviderTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) Loading Loading @@ -85,6 +86,25 @@ public class CardContentProviderTest { assertThat(rowsAfterInsert - rowsBeforeInsert).isEqualTo(2); } @Test @Config(qualifiers = "mcc999") public void bulkInsert_keepDismissalTimestamp_shouldHaveTimestamp() { mResolver.bulkInsert(mUri, generateTwoRowsWithDismissTimestamp()); mResolver.bulkInsert(mUri, generateTwoRows()); assertThat(queryDismissedTimestamp()).isEqualTo(10001L); } @Test public void bulkInsert_notKeepDismissalTimestamp_shouldNotHaveTimestamp() { mResolver.bulkInsert(mUri, generateTwoRowsWithDismissTimestamp()); mResolver.bulkInsert(mUri, generateTwoRows()); assertThat(queryDismissedTimestamp()).isEqualTo(0L); } @Test public void cardData_query() { mResolver.insert(mUri, generateOneRow()); Loading Loading @@ -198,10 +218,40 @@ public class CardContentProviderTest { return twoRows; } private ContentValues[] generateTwoRowsWithDismissTimestamp() { final ContentValues[] twoRows = new ContentValues[2]; twoRows[0] = generateOneRow(); final ContentValues values = new ContentValues(); values.put(CardDatabaseHelper.CardColumns.NAME, "toggle_airplane"); values.put(CardDatabaseHelper.CardColumns.TYPE, 1); values.put(CardDatabaseHelper.CardColumns.SCORE, 0.95); values.put(CardDatabaseHelper.CardColumns.SLICE_URI, "content://com.android.settings.slices/action/toggle_airplane"); values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2); values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings"); values.put(CardDatabaseHelper.CardColumns.APP_VERSION, 10001); values.put(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP, 10001L); twoRows[1] = values; return twoRows; } private int getRowCount() { final Cursor cr = mResolver.query(mUri, null, null, null); final int count = cr.getCount(); cr.close(); return count; } private long queryDismissedTimestamp() { final String[] columns = {CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP}; final String selection = CardDatabaseHelper.CardColumns.NAME + "=?"; final String[] selectionArgs = {"toggle_airplane"}; final Cursor cr = mResolver.query(mUri, columns, selection, selectionArgs, null); cr.moveToFirst(); final long dismissedTimestamp = cr.getLong(0); cr.close(); return dismissedTimestamp; } } No newline at end of file Loading
res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -201,6 +201,9 @@ <!-- Whether or not TopLevelSettings should force rounded icon for injected tiles --> <bool name="config_force_rounded_icon_TopLevelSettings">true</bool> <!-- Whether dismissal timestamp should be kept before deletion --> <bool name="config_keep_contextual_card_dismissal_timestamp">false</bool> <!-- Settings intelligence package name --> <string name="config_settingsintelligence_package_name" translatable="false"> com.android.settings.intelligence Loading
src/com/android/settings/homepage/contextualcards/CardContentProvider.java +45 −5 Original line number Diff line number Diff line Loading @@ -26,12 +26,16 @@ import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.os.Build; import android.os.StrictMode; import android.util.ArrayMap; import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settingslib.utils.ThreadUtils; import java.util.Map; /** * Provider stores and manages user interaction feedback for homepage contextual cards. */ Loading Loading @@ -81,6 +85,9 @@ public class CardContentProvider extends ContentProvider { final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); int numInserted = 0; final SQLiteDatabase database = mDBHelper.getWritableDatabase(); final boolean keepDismissalTimestampBeforeDeletion = getContext().getResources() .getBoolean(R.bool.config_keep_contextual_card_dismissal_timestamp); final Map<String, Long> dismissedTimeMap = new ArrayMap<>(); try { maybeEnableStrictMode(); Loading @@ -88,9 +95,42 @@ public class CardContentProvider extends ContentProvider { final String table = getTableFromMatch(uri); database.beginTransaction(); // Here deletion first is avoiding redundant insertion. According to cl/215350754 if (keepDismissalTimestampBeforeDeletion) { // Query the existing db and get dismissal info. final String[] columns = new String[]{CardDatabaseHelper.CardColumns.NAME, CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP}; final String selection = CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " IS NOT NULL"; try (Cursor cursor = database.query(table, columns, selection, null/* selectionArgs */, null /* groupBy */, null /* having */, null /* orderBy */)) { // Save them to a Map for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { final String cardName = cursor.getString(cursor.getColumnIndex( CardDatabaseHelper.CardColumns.NAME)); final long timestamp = cursor.getLong(cursor.getColumnIndex( CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP)); dismissedTimeMap.put(cardName, timestamp); } } } // Here delete data first to avoid redundant insertion. According to cl/215350754 database.delete(table, null /* whereClause */, null /* whereArgs */); for (ContentValues value : values) { if (keepDismissalTimestampBeforeDeletion) { // Replace dismissedTimestamp in each value if there is an old one. final String cardName = value.get(CardDatabaseHelper.CardColumns.NAME).toString(); if (dismissedTimeMap.containsKey(cardName)) { // Replace the value of dismissedTimestamp value.put(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP, dismissedTimeMap.get(cardName)); Log.d(TAG, "Replace dismissed time: " + cardName); } } long ret = database.insert(table, null /* nullColumnHack */, value); if (ret != -1L) { numInserted++; Loading
tests/robotests/res/values-mcc999/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,8 @@ <!-- Whether or not extra preview panels should be used for screen zoom setting. --> <bool name="config_enable_extra_screen_zoom_preview">false</bool> <!-- Whether dismissal timestamp should be kept before deletion --> <bool name="config_keep_contextual_card_dismissal_timestamp">true</bool> <!-- List of a11y components on the device allowed to be enabled by Settings Slices --> <string-array name="config_settings_slices_accessibility_components" translatable="false"> Loading
tests/robotests/src/com/android/settings/homepage/contextualcards/CardContentProviderTest.java +50 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) Loading Loading @@ -85,6 +86,25 @@ public class CardContentProviderTest { assertThat(rowsAfterInsert - rowsBeforeInsert).isEqualTo(2); } @Test @Config(qualifiers = "mcc999") public void bulkInsert_keepDismissalTimestamp_shouldHaveTimestamp() { mResolver.bulkInsert(mUri, generateTwoRowsWithDismissTimestamp()); mResolver.bulkInsert(mUri, generateTwoRows()); assertThat(queryDismissedTimestamp()).isEqualTo(10001L); } @Test public void bulkInsert_notKeepDismissalTimestamp_shouldNotHaveTimestamp() { mResolver.bulkInsert(mUri, generateTwoRowsWithDismissTimestamp()); mResolver.bulkInsert(mUri, generateTwoRows()); assertThat(queryDismissedTimestamp()).isEqualTo(0L); } @Test public void cardData_query() { mResolver.insert(mUri, generateOneRow()); Loading Loading @@ -198,10 +218,40 @@ public class CardContentProviderTest { return twoRows; } private ContentValues[] generateTwoRowsWithDismissTimestamp() { final ContentValues[] twoRows = new ContentValues[2]; twoRows[0] = generateOneRow(); final ContentValues values = new ContentValues(); values.put(CardDatabaseHelper.CardColumns.NAME, "toggle_airplane"); values.put(CardDatabaseHelper.CardColumns.TYPE, 1); values.put(CardDatabaseHelper.CardColumns.SCORE, 0.95); values.put(CardDatabaseHelper.CardColumns.SLICE_URI, "content://com.android.settings.slices/action/toggle_airplane"); values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2); values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings"); values.put(CardDatabaseHelper.CardColumns.APP_VERSION, 10001); values.put(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP, 10001L); twoRows[1] = values; return twoRows; } private int getRowCount() { final Cursor cr = mResolver.query(mUri, null, null, null); final int count = cr.getCount(); cr.close(); return count; } private long queryDismissedTimestamp() { final String[] columns = {CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP}; final String selection = CardDatabaseHelper.CardColumns.NAME + "=?"; final String[] selectionArgs = {"toggle_airplane"}; final Cursor cr = mResolver.query(mUri, columns, selection, selectionArgs, null); cr.moveToFirst(); final long dismissedTimestamp = cr.getLong(0); cr.close(); return dismissedTimestamp; } } No newline at end of file