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

Commit 2e5da48c authored by Jason Chiu's avatar Jason Chiu Committed by Android (Google) Code Review
Browse files

Merge "Reload homepage cards when necessary" into rvc-dev

parents 18490b2d e0327ee5
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
        }
    }

    void loadContextualCards(LoaderManager loaderManager) {
    void loadContextualCards(LoaderManager loaderManager, boolean restartLoaderNeeded) {
        if (mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) {
            Log.w(TAG, "Legacy suggestion contextual card enabled, skipping contextual cards.");
            return;
@@ -132,9 +132,17 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
        final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                new CardContentLoaderCallbacks(mContext);
        cardContentLoaderCallbacks.setListener(this);
        if (!restartLoaderNeeded) {
            // Use the cached data when navigating back to the first page and upon screen rotation.
            loaderManager.initLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
                    cardContentLoaderCallbacks);
        } else {
            // Reload all cards when navigating back after pressing home key, recent app key, or
            // turn off screen.
            mIsFirstLaunch = true;
            loaderManager.restartLoader(CARD_CONTENT_LOADER_ID, null /* bundle */,
                    cardContentLoaderCallbacks);
        }
    }

    private void loadCardControllers() {
@@ -194,7 +202,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
        // except Conditional cards, all other cards are from the database. So when the map sent
        // here is empty, we only keep Conditional cards.
        if (cardTypes.isEmpty()) {
            final Set<Integer> conditionalCardTypes = new TreeSet() {{
            final Set<Integer> conditionalCardTypes = new TreeSet<Integer>() {{
                add(ContextualCard.CardType.CONDITIONAL);
                add(ContextualCard.CardType.CONDITIONAL_HEADER);
                add(ContextualCard.CardType.CONDITIONAL_FOOTER);
+0 −2
Original line number Diff line number Diff line
@@ -135,8 +135,6 @@ public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.Vi
            // Adding items to empty list, should animate.
            mRecyclerView.scheduleLayoutAnimation();
        }

        //TODO(b/119465242): flickering conditional cards after collapsing/expanding
    }

    @Override
+10 −4
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.settings.homepage.contextualcards;

import static com.android.settings.intelligence.ContextualCardProto.ContextualCard.Category.IMPORTANT_VALUE;
import static com.android.settings.intelligence.ContextualCardProto.ContextualCard.Category.STICKY_VALUE;

import androidx.recyclerview.widget.DiffUtil;

import java.util.List;
@@ -52,11 +55,14 @@ public class ContextualCardsDiffCallback extends DiffUtil.Callback {

    @Override
    public boolean areContentsTheSame(int oldCardPosition, int newCardPosition) {
        // Slices with toggles needs to be updated continuously, which means their contents may
        // change. So here we assume the content will always be different to force view rebinding.
        if (mNewCards.get(newCardPosition).hasInlineAction()) {
        final ContextualCard newCard = mNewCards.get(newCardPosition);
        // Sticky, important, or toggleable slices need to be updated continuously, which means
        // their contents may change. So here we assume the content will always be different to
        // force view rebinding.
        if (newCard.getCategory() == STICKY_VALUE || newCard.getCategory() == IMPORTANT_VALUE
                || newCard.hasInlineAction()) {
            return false;
        }
        return mOldCards.get(oldCardPosition).equals(mNewCards.get(newCardPosition));
        return mOldCards.get(oldCardPosition).equals(newCard);
    }
}
 No newline at end of file
+113 −2
Original line number Diff line number Diff line
@@ -19,12 +19,18 @@ package com.android.settings.homepage.contextualcards;
import static com.android.settings.homepage.contextualcards.ContextualCardsAdapter.SPAN_COUNT;

import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper;
@@ -38,6 +44,17 @@ import com.android.settings.wifi.slice.ContextualWifiScanWorker;
public class ContextualCardsFragment extends InstrumentedFragment implements
        FocusRecyclerView.FocusListener {

    private static final String TAG = "ContextualCardsFragment";
    private static final boolean DEBUG = Build.IS_DEBUGGABLE;

    @VisibleForTesting
    static boolean sRestartLoaderNeeded;

    @VisibleForTesting
    BroadcastReceiver mKeyEventReceiver;
    @VisibleForTesting
    BroadcastReceiver mScreenOffReceiver;

    private FocusRecyclerView mCardsContainer;
    private GridLayoutManager mLayoutManager;
    private ContextualCardsAdapter mContextualCardsAdapter;
@@ -53,14 +70,30 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
        }
        mContextualCardManager = new ContextualCardManager(context, getSettingsLifecycle(),
                savedInstanceState);

        mKeyEventReceiver = new KeyEventReceiver();
    }

    @Override
    public void onStart() {
        super.onStart();
        registerScreenOffReceiver();
        registerKeyEventReceiver();
        ContextualWifiScanWorker.newVisibleUiSession();
        mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this));
        mContextualCardManager.loadContextualCards(LoaderManager.getInstance(this),
                sRestartLoaderNeeded);
        sRestartLoaderNeeded = false;
    }

    @Override
    public void onStop() {
        unregisterKeyEventReceiver();
        super.onStop();
    }

    @Override
    public void onDestroy() {
        unregisterScreenOffReceiver();
        super.onDestroy();
    }

    @Override
@@ -92,4 +125,82 @@ public class ContextualCardsFragment extends InstrumentedFragment implements
    public int getMetricsCategory() {
        return SettingsEnums.SETTINGS_HOMEPAGE;
    }

    private void registerKeyEventReceiver() {
        getActivity().registerReceiver(mKeyEventReceiver,
                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
    }

    private void unregisterKeyEventReceiver() {
        getActivity().unregisterReceiver(mKeyEventReceiver);
    }

    private void registerScreenOffReceiver() {
        if (mScreenOffReceiver == null) {
            mScreenOffReceiver = new ScreenOffReceiver();
            getActivity().registerReceiver(mScreenOffReceiver,
                    new IntentFilter(Intent.ACTION_SCREEN_OFF));
        }
    }

    private void unregisterScreenOffReceiver() {
        if (mScreenOffReceiver != null) {
            getActivity().unregisterReceiver(mScreenOffReceiver);
            mScreenOffReceiver = null;
        }
    }

    private void resetSession(Context context) {
        sRestartLoaderNeeded = true;
        unregisterScreenOffReceiver();
        FeatureFactory.getFactory(context).getSlicesFeatureProvider().newUiSession();
    }

    /**
     * Receiver for updating UI session when home key or recent app key is pressed.
     */
    @VisibleForTesting
    class KeyEventReceiver extends BroadcastReceiver {

        private static final String KEY_REASON = "reason";
        private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
        private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent == null || !Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                return;
            }

            final String reason = intent.getStringExtra(KEY_REASON);
            if (!SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)
                    && !SYSTEM_DIALOG_REASON_HOME_KEY.equals(reason)) {
                return;
            }

            if (DEBUG) {
                Log.d(TAG, "key pressed = " + reason);
            }
            resetSession(context);
        }
    }

    /**
     * Receiver for updating UI session when screen is turned off.
     */
    @VisibleForTesting
    class ScreenOffReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent == null || !Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
                return;
            }

            if (DEBUG) {
                Log.d(TAG, "screen off");
            }
            resetSession(context);
        }
    }
}
+7 −55
Original line number Diff line number Diff line
@@ -16,17 +16,14 @@
package com.android.settings.homepage.contextualcards.slices;

import static android.provider.Settings.Global.LOW_POWER_MODE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;

import static androidx.slice.builders.ListBuilder.ICON_IMAGE;

import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.net.Uri;
@@ -36,7 +33,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.VisibleForTesting;
@@ -52,8 +48,6 @@ import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBackgroundWorker;

import java.io.IOException;

public class DarkThemeSlice implements CustomSliceable {
    private static final String TAG = "DarkThemeSlice";
    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
@@ -97,11 +91,11 @@ public class DarkThemeSlice implements CustomSliceable {
        // Next time the Settings displays on screen again this card should no longer persist.
        if (DEBUG) {
            Log.d(TAG,
                    "!sKeepSliceShow = " + !sKeepSliceShow + " !sSliceClicked = "
                            + !sSliceClicked + " !isAvailable = " + !isAvailable(mContext));
                    "sKeepSliceShow = " + sKeepSliceShow + ", sSliceClicked = " + sSliceClicked
                            + ", isAvailable = " + isAvailable(mContext));
        }
        if (mPowerManager.isPowerSaveMode() || ((!sKeepSliceShow || !sSliceClicked)
                && !isAvailable(mContext))) {
        if (mPowerManager.isPowerSaveMode()
                || ((!sKeepSliceShow || !sSliceClicked) && !isAvailable(mContext))) {
            return new ListBuilder(mContext, CustomSliceRegistry.DARK_THEME_SLICE_URI,
                    ListBuilder.INFINITY)
                    .setIsError(true)
@@ -188,7 +182,7 @@ public class DarkThemeSlice implements CustomSliceable {
    private boolean isNightModeScheduled() {
        final int mode = mUiModeManager.getNightMode();
        if (DEBUG) {
            Log.d(TAG, "night mode : " + mode);
            Log.d(TAG, "night mode = " + mode);
        }
        // Turn on from sunset to sunrise or turn on at custom time
        if (mode == UiModeManager.MODE_NIGHT_AUTO || mode == UiModeManager.MODE_NIGHT_CUSTOM) {
@@ -208,12 +202,10 @@ public class DarkThemeSlice implements CustomSliceable {
                        }
                    }
                };
        private final HomeKeyReceiver mHomeKeyReceiver;

        public DarkThemeWorker(Context context, Uri uri) {
            super(context, uri);
            mContext = context;
            mHomeKeyReceiver = new HomeKeyReceiver();
        }

        @Override
@@ -221,55 +213,15 @@ public class DarkThemeSlice implements CustomSliceable {
            mContext.getContentResolver().registerContentObserver(
                    Settings.Global.getUriFor(LOW_POWER_MODE), false /* notifyForDescendants */,
                    mContentObserver);
            final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
            mContext.registerReceiver(mHomeKeyReceiver, intentFilter);
        }

        @Override
        protected void onSliceUnpinned() {
            mContext.getContentResolver().unregisterContentObserver(mContentObserver);
            mContext.unregisterReceiver(mHomeKeyReceiver);
        }

        @Override
        public void close() throws IOException {
        }
    }

    /**
     * A receiver for Home key and recent app key.
     */
    public static class HomeKeyReceiver extends BroadcastReceiver {
        private static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
        private static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        private static final String SYSTEM_DIALOG_REASON_KEY = "reason";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (TextUtils.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS, intent.getAction())) {
                if (TextUtils.equals(getTargetKey(context),
                        intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY))) {
                    if (DEBUG) {
                        Log.d(TAG, "HomeKeyReceiver : target key = " + getTargetKey(context));
                    }
                    if (DarkThemeSlice.isDarkThemeMode(context)) {
                        FeatureFactory.getFactory(
                                context).getSlicesFeatureProvider().newUiSession();
                    }
                }
            }
        }

        private String getTargetKey(Context context) {
            if (isGestureNavigationEnabled(context)) {
                return SYSTEM_DIALOG_REASON_RECENT_APPS;
            }
            return SYSTEM_DIALOG_REASON_HOME_KEY;
        }

        private boolean isGestureNavigationEnabled(Context context) {
            return NAV_BAR_MODE_GESTURAL == context.getResources().getInteger(
                    com.android.internal.R.integer.config_navBarInteractionMode);
        public void close() {
        }
    }
}
Loading