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

Commit 4f80f221 authored by William Luh's avatar William Luh
Browse files

Query the security feature provider on separate threads.

Bug: 35065510
Test: make RunSettingsRoboTests
Change-Id: Ib9ffc5bf9c3ace5d2a904206f834f69eccfb690d
parent c65e3a19
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;

import java.util.ArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.List;

import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
@@ -1032,8 +1034,8 @@ public class SecuritySettings extends SettingsPreferenceFragment
                        MY_USER_ID));
            }
            if (mPowerButtonInstantlyLocks != null) {
                mPowerButtonInstantlyLocks.setChecked(mLockPatternUtils.getPowerButtonInstantlyLocks(
                        MY_USER_ID));
                mPowerButtonInstantlyLocks.setChecked(
                        mLockPatternUtils.getPowerButtonInstantlyLocks(MY_USER_ID));
            }

            updateOwnerInfo();
@@ -1297,9 +1299,18 @@ public class SecuritySettings extends SettingsPreferenceFragment
                    FeatureFactory.getFactory(mContext).getDashboardFeatureProvider(mContext);
            if (dashboardFeatureProvider.isEnabled()
                    && (packageVerifierState == PACKAGE_VERIFIER_STATE_ENABLED)) {
                // Calling the feature provider could potentially be slow, so do this on a separate
                // thread so as to not block the loading of Settings.
                Executors.newSingleThreadExecutor().execute(new Runnable() {
                    @Override
                    public void run() {
                        DashboardCategory dashboardCategory =
                        dashboardFeatureProvider.getTilesForCategory(CategoryKey.CATEGORY_SECURITY);
                mSummaryLoader.setSummary(this, getPackageVerifierSummary(dashboardCategory));
                                dashboardFeatureProvider.getTilesForCategory(
                                        CategoryKey.CATEGORY_SECURITY);
                        mSummaryLoader.setSummary(SummaryProvider.this,
                                getPackageVerifierSummary(dashboardCategory));
                    }
                });
            } else {
                final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(mContext);
                if (fpm != null && fpm.isHardwareDetected()) {
+48 −15
Original line number Diff line number Diff line
@@ -22,9 +22,12 @@ import android.content.IContentProvider;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import com.android.settings.trustagent.TrustAgentManager;
import com.android.settings.trustagent.TrustAgentManagerImpl;
import com.android.settingslib.drawer.DashboardCategory;
import android.support.annotation.VisibleForTesting;
import android.support.v4.content.ContextCompat;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
@@ -35,6 +38,7 @@ import android.util.Pair;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;

import java.util.concurrent.Executors;
import java.util.Map;

/** Implementation for {@code SecurityFeatureProvider}. */
@@ -43,8 +47,22 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
    private TrustAgentManager mTrustAgentManager;

    /** Update preferences with data from associated tiles. */
    public void updatePreferences(Context context, PreferenceScreen preferenceScreen,
    public void updatePreferences(final Context context, final PreferenceScreen preferenceScreen,
            final DashboardCategory dashboardCategory) {
        // Fetching the summary and icon from the provider introduces latency, so do this on a
        // separate thread.
        Executors.newSingleThreadExecutor().execute(new Runnable() {
            @Override
            public void run() {
                updatePreferencesToRunOnWorkerThread(context, preferenceScreen, dashboardCategory);
            }
        });
    }

    @VisibleForTesting
    void updatePreferencesToRunOnWorkerThread(Context context, PreferenceScreen preferenceScreen,
            DashboardCategory dashboardCategory) {

        if (preferenceScreen == null) {
            return;
        }
@@ -82,18 +100,31 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
                        TileUtils.getIconFromUri(context, packageName, iconUri, providerMap);
                if (icon != null) {
                    // Icon is only returned if the icon belongs to Settings or the target app.
                    // setIcon must be called on the UI thread.
                    new Handler(Looper.getMainLooper()).post(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                matchingPref.setIcon(context.getPackageManager()
                                        .getResourcesForApplication(icon.first /* package name */)
                                        .getDrawable(icon.second /* res id */, context.getTheme()));
                    } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
                        // Intentionally ignored. If icon resources cannot be found, do not update.
                                                .getDrawable(icon.second /* res id */,
                                                        context.getTheme()));
                            } catch (PackageManager.NameNotFoundException
                                    | Resources.NotFoundException e) {
                                // Intentionally ignored. If icon resources cannot be found, do not
                                // update.
                            }
                        }
                    });
                }
            }
            if (!TextUtils.isEmpty(summaryUri)) {
                String summary = TileUtils.getTextFromUri(context, summaryUri, providerMap,
                        TileUtils.META_DATA_PREFERENCE_SUMMARY);
                // setSummary must be called on UI thread.
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        // Only update the summary if it has actually changed.
                        if (summary == null) {
                            if (matchingPref.getSummary() != null) {
@@ -103,6 +134,8 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
                            matchingPref.setSummary(summary);
                        }
                    }
                });
            }
        }
    }

+16 −6
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowLooper;

import java.util.Map;

@@ -102,8 +103,11 @@ public class SecurityFeatureProviderImplTest {

    @Test
    public void updateTilesData_shouldNotProcessEmptyScreenOrTiles() {
        mImpl.updatePreferences(mContext, null, null);
        mImpl.updatePreferences(mContext, new PreferenceScreen(mContext, null), null);
        mImpl.updatePreferencesToRunOnWorkerThread(mContext, null, null);
        ShadowLooper.runUiThreadTasks();
        mImpl.updatePreferencesToRunOnWorkerThread(
                mContext, new PreferenceScreen(mContext, null), null);
        ShadowLooper.runUiThreadTasks();
        verifyNoMoreInteractions(mPackageManager);
    }

@@ -111,13 +115,17 @@ public class SecurityFeatureProviderImplTest {
    public void updateTilesData_shouldNotProcessNonMatchingPreference() {
        DashboardCategory dashboardCategory = new DashboardCategory();
        dashboardCategory.addTile(new Tile());
        mImpl.updatePreferences(mContext, getPreferenceScreen(), dashboardCategory);
        mImpl.updatePreferencesToRunOnWorkerThread(
                mContext, getPreferenceScreen(), dashboardCategory);
        ShadowLooper.runUiThreadTasks();
        verifyNoMoreInteractions(mPackageManager);
    }

    @Test
    public void updateTilesData_shouldNotProcessMatchingPreferenceWithNoData() {
        mImpl.updatePreferences(mContext, getPreferenceScreen(), getDashboardCategory());
        mImpl.updatePreferencesToRunOnWorkerThread(
                mContext, getPreferenceScreen(), getDashboardCategory());
        ShadowLooper.runUiThreadTasks();
        verifyNoMoreInteractions(mPackageManager);
    }

@@ -135,7 +143,8 @@ public class SecurityFeatureProviderImplTest {
        dashboardCategory.getTile(0).intent = new Intent().setPackage("package");
        dashboardCategory.getTile(0).metaData = bundle;

        mImpl.updatePreferences(mContext, screen, dashboardCategory);
        mImpl.updatePreferencesToRunOnWorkerThread(mContext, screen, dashboardCategory);
        ShadowLooper.runUiThreadTasks();
        verify(screen.findPreference(MOCK_KEY)).setIcon(mMockDrawable);
        verify(screen.findPreference(MOCK_KEY)).setSummary(MOCK_SUMMARY);
    }
@@ -157,7 +166,8 @@ public class SecurityFeatureProviderImplTest {
        dashboardCategory.getTile(0).intent = new Intent().setPackage("package");
        dashboardCategory.getTile(0).metaData = bundle;

        mImpl.updatePreferences(mContext, screen, dashboardCategory);
        mImpl.updatePreferencesToRunOnWorkerThread(mContext, screen, dashboardCategory);
        ShadowLooper.runUiThreadTasks();
        verify(screen.findPreference(MOCK_KEY), never()).setSummary(anyString());
    }