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

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

Merge "Reduce flickers of Injection" into tm-dev

parents e05d71b7 c9615611
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ public class CategoryMixin implements LifecycleObserver {
    private final PackageReceiver mPackageReceiver = new PackageReceiver();
    private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
    private int mCategoriesUpdateTaskCount;
    private boolean mFirstOnResume = true;

    public CategoryMixin(Context context) {
        mContext = context;
@@ -75,6 +76,12 @@ public class CategoryMixin implements LifecycleObserver {
        filter.addDataScheme(DATA_SCHEME_PKG);
        mContext.registerReceiver(mPackageReceiver, filter);

        if (mFirstOnResume) {
            // Skip since all tiles have been refreshed in DashboardFragment.onCreatePreferences().
            Log.d(TAG, "Skip categories update");
            mFirstOnResume = false;
            return;
        }
        updateCategories();
    }

+9 −12
Original line number Diff line number Diff line
@@ -235,13 +235,13 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
            public void onDataChanged() {
                switch (method) {
                    case METHOD_GET_DYNAMIC_TITLE:
                        refreshTitle(uri, pref);
                        refreshTitle(uri, pref, this);
                        break;
                    case METHOD_GET_DYNAMIC_SUMMARY:
                        refreshSummary(uri, pref);
                        refreshSummary(uri, pref, this);
                        break;
                    case METHOD_IS_CHECKED:
                        refreshSwitch(uri, pref);
                        refreshSwitch(uri, pref, this);
                        break;
                }
            }
@@ -262,19 +262,18 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {

            final Uri uri = TileUtils.getCompleteUri(tile, META_DATA_PREFERENCE_TITLE_URI,
                    METHOD_GET_DYNAMIC_TITLE);
            refreshTitle(uri, preference);
            return createDynamicDataObserver(METHOD_GET_DYNAMIC_TITLE, uri, preference);
        }
        return null;
    }

    private void refreshTitle(Uri uri, Preference preference) {
    private void refreshTitle(Uri uri, Preference preference, DynamicDataObserver observer) {
        ThreadUtils.postOnBackgroundThread(() -> {
            final Map<String, IContentProvider> providerMap = new ArrayMap<>();
            final String titleFromUri = TileUtils.getTextFromUri(
                    mContext, uri, providerMap, META_DATA_PREFERENCE_TITLE);
            if (!TextUtils.equals(titleFromUri, preference.getTitle())) {
                ThreadUtils.postOnMainThread(() -> preference.setTitle(titleFromUri));
                observer.post(() -> preference.setTitle(titleFromUri));
            }
        });
    }
@@ -291,19 +290,18 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {

            final Uri uri = TileUtils.getCompleteUri(tile, META_DATA_PREFERENCE_SUMMARY_URI,
                    METHOD_GET_DYNAMIC_SUMMARY);
            refreshSummary(uri, preference);
            return createDynamicDataObserver(METHOD_GET_DYNAMIC_SUMMARY, uri, preference);
        }
        return null;
    }

    private void refreshSummary(Uri uri, Preference preference) {
    private void refreshSummary(Uri uri, Preference preference, DynamicDataObserver observer) {
        ThreadUtils.postOnBackgroundThread(() -> {
            final Map<String, IContentProvider> providerMap = new ArrayMap<>();
            final String summaryFromUri = TileUtils.getTextFromUri(
                    mContext, uri, providerMap, META_DATA_PREFERENCE_SUMMARY);
            if (!TextUtils.equals(summaryFromUri, preference.getSummary())) {
                ThreadUtils.postOnMainThread(() -> preference.setSummary(summaryFromUri));
                observer.post(() -> preference.setSummary(summaryFromUri));
            }
        });
    }
@@ -323,7 +321,6 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
        final Uri isCheckedUri = TileUtils.getCompleteUri(tile, META_DATA_PREFERENCE_SWITCH_URI,
                METHOD_IS_CHECKED);
        setSwitchEnabled(preference, false);
        refreshSwitch(isCheckedUri, preference);
        return createDynamicDataObserver(METHOD_IS_CHECKED, isCheckedUri, preference);
    }

@@ -350,12 +347,12 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
        });
    }

    private void refreshSwitch(Uri uri, Preference preference) {
    private void refreshSwitch(Uri uri, Preference preference, DynamicDataObserver observer) {
        ThreadUtils.postOnBackgroundThread(() -> {
            final Map<String, IContentProvider> providerMap = new ArrayMap<>();
            final boolean checked = TileUtils.getBooleanFromUri(mContext, uri, providerMap,
                    EXTRA_SWITCH_CHECKED_STATE);
            ThreadUtils.postOnMainThread(() -> {
            observer.post(() -> {
                setSwitchChecked(preference, checked);
                setSwitchEnabled(preference, true);
            });
+38 −9
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.settings.dashboard;

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context;
@@ -57,6 +56,8 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * Base fragment for dashboard style UI containing a list of static and dynamic setting items.
@@ -66,6 +67,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
        BasePreferenceController.UiBlockListener {
    public static final String CATEGORY = "category";
    private static final String TAG = "DashboardFragment";
    private static final long TIMEOUT_MILLIS = 50L;

    @VisibleForTesting
    final ArrayMap<String, List<DynamicDataObserver>> mDashboardTilePrefKeys = new ArrayMap<>();
@@ -461,8 +463,9 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
        // Create a list to track which tiles are to be removed.
        final Map<String, List<DynamicDataObserver>> remove = new ArrayMap(mDashboardTilePrefKeys);

        // Install dashboard tiles.
        // Install dashboard tiles and collect pending observers.
        final boolean forceRoundedIcons = shouldForceRoundedIcon();
        final List<DynamicDataObserver> pendingObservers = new ArrayList<>();
        for (Tile tile : tiles) {
            final String key = mDashboardFeatureProvider.getDashboardKeyForTile(tile);
            if (TextUtils.isEmpty(key)) {
@@ -472,26 +475,30 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
            if (!displayTile(tile)) {
                continue;
            }
            final List<DynamicDataObserver> observers;
            if (mDashboardTilePrefKeys.containsKey(key)) {
                // Have the key already, will rebind.
                final Preference preference = screen.findPreference(key);
                mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(getActivity(), this,
                        forceRoundedIcons, preference, tile, key,
                observers = mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(
                        getActivity(), this, forceRoundedIcons, preference, tile, key,
                        mPlaceholderPreferenceController.getOrder());
            } else {
                // Don't have this key, add it.
                final Preference pref = createPreference(tile);
                final List<DynamicDataObserver> observers =
                        mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(getActivity(),
                                this, forceRoundedIcons, pref, tile, key,
                observers = mDashboardFeatureProvider.bindPreferenceToTileAndGetObservers(
                        getActivity(), this, forceRoundedIcons, pref, tile, key,
                        mPlaceholderPreferenceController.getOrder());
                screen.addPreference(pref);
                registerDynamicDataObservers(observers);
                mDashboardTilePrefKeys.put(key, observers);
            }
            if (observers != null) {
                pendingObservers.addAll(observers);
            }
            remove.remove(key);
        }
        // Finally remove tiles that are gone.

        // Remove tiles that are gone.
        for (Map.Entry<String, List<DynamicDataObserver>> entry : remove.entrySet()) {
            final String key = entry.getKey();
            mDashboardTilePrefKeys.remove(key);
@@ -501,6 +508,20 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
            }
            unregisterDynamicDataObservers(entry.getValue());
        }

        // Wait for pending observers to update UI.
        if (!pendingObservers.isEmpty()) {
            final CountDownLatch mainLatch = new CountDownLatch(1);
            new Thread(() -> {
                pendingObservers.forEach(observer ->
                        awaitObserverLatch(observer.getCountDownLatch()));
                mainLatch.countDown();
            }).start();
            Log.d(tag, "Start waiting observers");
            awaitObserverLatch(mainLatch);
            Log.d(tag, "Stop waiting observers");
            pendingObservers.forEach(DynamicDataObserver::updateUi);
        }
    }

    @Override
@@ -546,4 +567,12 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
            resolver.unregisterContentObserver(observer);
        });
    }

    private void awaitObserverLatch(CountDownLatch latch) {
        try {
            latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            // Do nothing
        }
    }
}
+33 −0
Original line number Diff line number Diff line
@@ -20,13 +20,24 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;

import com.android.settingslib.utils.ThreadUtils;

import java.util.concurrent.CountDownLatch;

/**
 * Observer for updating injected dynamic data.
 */
public abstract class DynamicDataObserver extends ContentObserver {

    private Runnable mUpdateRunnable;
    private CountDownLatch mCountDownLatch;
    private boolean mUpdateDelegated;

    protected DynamicDataObserver() {
        super(new Handler(Looper.getMainLooper()));
        mCountDownLatch = new CountDownLatch(1);
        // Load data for the first time
        onDataChanged();
    }

    /** Returns the uri of the callback. */
@@ -35,8 +46,30 @@ public abstract class DynamicDataObserver extends ContentObserver {
    /** Called when data changes. */
    public abstract void onDataChanged();

    /** Calls the runnable to update UI */
    public synchronized void updateUi() {
        mUpdateDelegated = true;
        if (mUpdateRunnable != null) {
            mUpdateRunnable.run();
        }
    }

    /** Returns the count-down latch */
    public CountDownLatch getCountDownLatch() {
        return mCountDownLatch;
    }

    @Override
    public void onChange(boolean selfChange) {
        onDataChanged();
    }

    protected synchronized void post(Runnable runnable) {
        if (mUpdateDelegated) {
            ThreadUtils.postOnMainThread(runnable);
        } else {
            mUpdateRunnable = runnable;
            mCountDownLatch.countDown();
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ public class BluetoothDevicesSlice implements CustomSliceable {
    List<CachedBluetoothDevice> getPairedBluetoothDevices() {
        final List<CachedBluetoothDevice> bluetoothDeviceList = new ArrayList<>();

        // If Bluetooth is disable, skip getting the Bluetooth devices.
        // If Bluetooth is disabled, skip getting the Bluetooth devices.
        if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
            Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
            return bluetoothDeviceList;
Loading