Merge "Keep contextual card dismissal info upon deletion"

This commit is contained in:
TreeHugger Robot
2020-02-22 12:49:40 +00:00
committed by Android (Google) Code Review
4 changed files with 100 additions and 5 deletions

View File

@@ -201,6 +201,9 @@
<!-- Whether or not TopLevelSettings should force rounded icon for injected tiles --> <!-- Whether or not TopLevelSettings should force rounded icon for injected tiles -->
<bool name="config_force_rounded_icon_TopLevelSettings">true</bool> <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 --> <!-- Settings intelligence package name -->
<string name="config_settingsintelligence_package_name" translatable="false"> <string name="config_settingsintelligence_package_name" translatable="false">
com.android.settings.intelligence com.android.settings.intelligence

View File

@@ -26,12 +26,16 @@ import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.StrictMode; import android.os.StrictMode;
import android.util.ArrayMap;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import java.util.Map;
/** /**
* Provider stores and manages user interaction feedback for homepage contextual cards. * Provider stores and manages user interaction feedback for homepage contextual cards.
*/ */
@@ -40,10 +44,10 @@ public class CardContentProvider extends ContentProvider {
public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider"; public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider";
public static final Uri REFRESH_CARD_URI = new Uri.Builder() public static final Uri REFRESH_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT) .scheme(ContentResolver.SCHEME_CONTENT)
.authority(CardContentProvider.CARD_AUTHORITY) .authority(CardContentProvider.CARD_AUTHORITY)
.appendPath(CardDatabaseHelper.CARD_TABLE) .appendPath(CardDatabaseHelper.CARD_TABLE)
.build(); .build();
public static final Uri DELETE_CARD_URI = new Uri.Builder() public static final Uri DELETE_CARD_URI = new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT) .scheme(ContentResolver.SCHEME_CONTENT)
@@ -81,6 +85,9 @@ public class CardContentProvider extends ContentProvider {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
int numInserted = 0; int numInserted = 0;
final SQLiteDatabase database = mDBHelper.getWritableDatabase(); 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 { try {
maybeEnableStrictMode(); maybeEnableStrictMode();
@@ -88,9 +95,42 @@ public class CardContentProvider extends ContentProvider {
final String table = getTableFromMatch(uri); final String table = getTableFromMatch(uri);
database.beginTransaction(); 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 */); database.delete(table, null /* whereClause */, null /* whereArgs */);
for (ContentValues value : values) { 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); long ret = database.insert(table, null /* nullColumnHack */, value);
if (ret != -1L) { if (ret != -1L) {
numInserted++; numInserted++;

View File

@@ -72,6 +72,8 @@
<!-- Whether or not extra preview panels should be used for screen zoom setting. --> <!-- Whether or not extra preview panels should be used for screen zoom setting. -->
<bool name="config_enable_extra_screen_zoom_preview">false</bool> <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 --> <!-- List of a11y components on the device allowed to be enabled by Settings Slices -->
<string-array name="config_settings_slices_accessibility_components" translatable="false"> <string-array name="config_settings_slices_accessibility_components" translatable="false">

View File

@@ -38,6 +38,7 @@ import org.junit.runner.RunWith;
import org.robolectric.Robolectric; import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers; import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@@ -85,6 +86,25 @@ public class CardContentProviderTest {
assertThat(rowsAfterInsert - rowsBeforeInsert).isEqualTo(2); 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 @Test
public void cardData_query() { public void cardData_query() {
mResolver.insert(mUri, generateOneRow()); mResolver.insert(mUri, generateOneRow());
@@ -198,10 +218,40 @@ public class CardContentProviderTest {
return twoRows; 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() { private int getRowCount() {
final Cursor cr = mResolver.query(mUri, null, null, null); final Cursor cr = mResolver.query(mUri, null, null, null);
final int count = cr.getCount(); final int count = cr.getCount();
cr.close(); cr.close();
return count; 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;
}
} }