Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 806d2fc5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement new dismissal behaviour of contextual card"

parents 3c96925a deea015b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ public class CardContentProvider extends ContentProvider {
    public static final Uri DELETE_CARD_URI = new Uri.Builder()
            .scheme(ContentResolver.SCHEME_CONTENT)
            .authority(CardContentProvider.CARD_AUTHORITY)
            .appendPath(CardDatabaseHelper.CardColumns.CARD_DISMISSED)
            .appendPath(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP)
            .build();

    private static final String TAG = "CardContentProvider";
+23 −52
Original line number Diff line number Diff line
@@ -16,9 +16,7 @@

package com.android.settings.homepage.contextualcards;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
@@ -31,7 +29,7 @@ import androidx.annotation.VisibleForTesting;
public class CardDatabaseHelper extends SQLiteOpenHelper {
    private static final String TAG = "CardDatabaseHelper";
    private static final String DATABASE_NAME = "homepage_cards.db";
    private static final int DATABASE_VERSION = 6;
    private static final int DATABASE_VERSION = 7;

    public static final String CARD_TABLE = "cards";

@@ -72,31 +70,32 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
        String APP_VERSION = "app_version";

        /**
         * Decide the card is dismissed or not.
         * Timestamp of card being dismissed.
         */
        String CARD_DISMISSED = "card_dismissed";
        String DISMISSED_TIMESTAMP = "dismissed_timestamp";
    }

    private static final String CREATE_CARD_TABLE =
            "CREATE TABLE " + CARD_TABLE +
                    "(" +
                    CardColumns.NAME +
                    " TEXT NOT NULL PRIMARY KEY, " +
                    CardColumns.TYPE +
                    " INTEGER NOT NULL, " +
                    CardColumns.SCORE +
                    " DOUBLE NOT NULL, " +
                    CardColumns.SLICE_URI +
                    " TEXT, " +
                    CardColumns.CATEGORY +
                    " INTEGER DEFAULT 0, " +
                    CardColumns.PACKAGE_NAME +
                    " TEXT NOT NULL, " +
                    CardColumns.APP_VERSION +
                    " INTEGER NOT NULL, " +
                    CardColumns.CARD_DISMISSED +
                    " INTEGER DEFAULT 0 " +
                    ");";
            "CREATE TABLE "
                    + CARD_TABLE
                    + "("
                    + CardColumns.NAME
                    + " TEXT NOT NULL PRIMARY KEY, "
                    + CardColumns.TYPE
                    + " INTEGER NOT NULL, "
                    + CardColumns.SCORE
                    + " DOUBLE NOT NULL, "
                    + CardColumns.SLICE_URI
                    + " TEXT, "
                    + CardColumns.CATEGORY
                    + " INTEGER DEFAULT 0, "
                    + CardColumns.PACKAGE_NAME
                    + " TEXT NOT NULL, "
                    + CardColumns.APP_VERSION
                    + " INTEGER NOT NULL, "
                    + CardColumns.DISMISSED_TIMESTAMP
                    + " INTEGER"
                    + ");";

    public CardDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -125,32 +124,4 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
        }
        return sCardDatabaseHelper;
    }

    Cursor getContextualCards() {
        final SQLiteDatabase db = getReadableDatabase();
        final String selection = CardColumns.CARD_DISMISSED + "=0";
        return db.query(CARD_TABLE, null /* columns */, selection,
                null /* selectionArgs */, null /* groupBy */, null /* having */,
                CardColumns.SCORE + " DESC" /* orderBy */);
    }

    /**
     * Mark a specific ContextualCard with dismissal flag in the database to indicate that the
     * card has been dismissed.
     *
     * @param context  Context
     * @param cardName The card name of the ContextualCard which is dismissed by user.
     * @return The number of rows updated
     */
    public int markContextualCardAsDismissed(Context context, String cardName) {
        final SQLiteDatabase database = getWritableDatabase();
        final ContentValues values = new ContentValues();
        values.put(CardColumns.CARD_DISMISSED, 1);
        final String selection = CardColumns.NAME + "=?";
        final String[] selectionArgs = {cardName};
        final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
        database.close();
        context.getContentResolver().notifyChange(CardContentProvider.DELETE_CARD_URI, null);
        return rowsUpdated;
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -16,10 +16,25 @@

package com.android.settings.homepage.contextualcards;

import android.content.Context;
import android.database.Cursor;

import androidx.slice.Slice;

/** Feature provider for the contextual card feature. */
public interface ContextualCardFeatureProvider {
    /** Get contextual cards from the card provider */
    Cursor getContextualCards();

    /**
     * Mark a specific {@link ContextualCard} as dismissed with dismissal signal in the database
     * to indicate that the card has been dismissed.
     *
     * @param context  Context
     * @param cardName The card name of the ContextualCard which is dismissed by user.
     * @return The number of rows updated
     */
    int markCardAsDismissed(Context context, String cardName);

    /** Log package when user clicks contextual notification channel card. */
    void logNotificationPackage(Slice slice);
+55 −0
Original line number Diff line number Diff line
@@ -18,10 +18,19 @@ package com.android.settings.homepage.contextualcards;

import static android.content.Context.MODE_PRIVATE;

import static com.android.settings.homepage.contextualcards.CardDatabaseHelper.CARD_TABLE;

import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
import androidx.slice.core.SliceAction;
@@ -30,16 +39,46 @@ import com.android.settings.SettingsActivity;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.homepage.contextualcards.slices.ContextualNotificationChannelSlice;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settingslib.utils.ThreadUtils;

import java.util.Set;

public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureProvider {
    private static final String TAG = "ContextualCardFeatureProvider";

    private final Context mContext;

    public ContextualCardFeatureProviderImpl(Context context) {
        mContext = context;
    }

    @Override
    public Cursor getContextualCards() {
        final SQLiteDatabase db = CardDatabaseHelper.getInstance(mContext).getReadableDatabase();
        //TODO(b/149542061): Make the dismissal duration configurable.
        final long threshold = System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS;
        final String selection = CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " < ? OR "
                + CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " IS NULL";
        final String[] selectionArgs = {String.valueOf(threshold)};
        final Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
                selectionArgs /* selectionArgs */, null /* groupBy */, null /* having */,
                CardDatabaseHelper.CardColumns.SCORE + " DESC" /* orderBy */);
        ThreadUtils.postOnBackgroundThread(() -> resetDismissedTime(threshold));
        return cursor;
    }

    @Override
    public int markCardAsDismissed(Context context, String cardName) {
        final SQLiteDatabase db = CardDatabaseHelper.getInstance(mContext).getWritableDatabase();
        final ContentValues values = new ContentValues();
        values.put(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP, System.currentTimeMillis());
        final String selection = CardDatabaseHelper.CardColumns.NAME + "=?";
        final String[] selectionArgs = {cardName};
        final int rowsUpdated = db.update(CARD_TABLE, values, selection, selectionArgs);
        context.getContentResolver().notifyChange(CardContentProvider.DELETE_CARD_URI, null);
        return rowsUpdated;
    }

    @Override
    public void logNotificationPackage(Slice slice) {
        if (slice == null || !slice.getUri().equals(
@@ -62,4 +101,20 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
        prefs.edit().putStringSet(ContextualNotificationChannelSlice.PREF_KEY_INTERACTED_PACKAGES,
                newInteractedPackages).apply();
    }

    @VisibleForTesting
    int resetDismissedTime(long threshold) {
        final SQLiteDatabase database =
                CardDatabaseHelper.getInstance(mContext).getWritableDatabase();
        final ContentValues values = new ContentValues();
        values.putNull(CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP);
        final String selection = CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " < ? AND "
                + CardDatabaseHelper.CardColumns.DISMISSED_TIMESTAMP + " IS NOT NULL";
        final String[] selectionArgs = {String.valueOf(threshold)};
        final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
        if (Build.IS_DEBUGGABLE) {
            Log.d(TAG, "Reset " + rowsUpdated + " records of dismissed time.");
        }
        return rowsUpdated;
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -178,7 +178,9 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>

    @VisibleForTesting
    Cursor getContextualCardsFromProvider() {
        return CardDatabaseHelper.getInstance(mContext).getContextualCards();
        final ContextualCardFeatureProvider cardFeatureProvider =
                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
        return cardFeatureProvider.getContextualCards();
    }

    @VisibleForTesting
Loading