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

Commit 8cc6f9f7 authored by Daniel Nishi's avatar Daniel Nishi
Browse files

Add click behavior to the storage item preferences.

This currently imitates the previous implementation behavior.
The new mocks have a new intermediate view for some of these
behaviors, but this view isn't ready yet.
This patch should bring parity for the click functionality
for the storage line item preferences.

Bug: 33199077
Test: Settings Robo Tests

Change-Id: I4f654d30add92e4eec721c36b2801f9af9824e78
parent c8cae26b
Loading
Loading
Loading
Loading
+6 −12
Original line number Diff line number Diff line
@@ -21,32 +21,26 @@
        android:key="pref_summary" />
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_photos_videos"
        android:title="@string/storage_photos_videos"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_photos_videos">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_music_audio"
        android:title="@string/storage_music_audio"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_music_audio">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_games"
        android:title="@string/storage_games"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_games">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_other_apps"
        android:title="@string/storage_other_apps"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_other_apps">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_system"
        android:title="@string/storage_detail_system"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_detail_system">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
    <com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate
        android:key="pref_files"
        android:title="@string/storage_files"
        android:fragment="com.android.settings.deletionhelper.AutomaticStorageManagerSettings">
        android:title="@string/storage_files">
    </com.android.settings.deviceinfo.storage.StorageItemPreferenceAlternate>
</PreferenceScreen>
 No newline at end of file
+8 −6
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.FooterPreference;
import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider;
import com.android.settingslib.drawer.CategoryKey;

import java.util.ArrayList;
@@ -48,6 +49,7 @@ public class StorageDashboardFragment extends DashboardFragment {
    private long mTotalSize;

    private StorageSummaryDonutPreferenceController mSummaryController;
    private StorageItemPreferenceController mPreferenceController;

    private boolean isVolumeValid() {
        return (mVolume != null) && (mVolume.getType() == VolumeInfo.TYPE_PRIVATE)
@@ -78,6 +80,7 @@ public class StorageDashboardFragment extends DashboardFragment {

        final long usedBytes = mTotalSize - mVolume.getPath().getFreeSpace();
        mSummaryController.updateBytes(usedBytes, mTotalSize);
        mPreferenceController.setVolume(mVolume);

        // Initialize the footer preference to go to the smart storage management.
        final FooterPreference pref = mFooterPreferenceMixin.createFooterPreference();
@@ -114,13 +117,12 @@ public class StorageDashboardFragment extends DashboardFragment {
        final List<PreferenceController> controllers = new ArrayList<>();
        mSummaryController = new StorageSummaryDonutPreferenceController(context);
        controllers.add(mSummaryController);

        StorageManager sm = context.getSystemService(StorageManager.class);
        mPreferenceController = new StorageItemPreferenceController(context, this, mVolume,
                new StorageManagerVolumeProvider(sm));
        controllers.add(mPreferenceController);
        controllers.add(new ManageStoragePreferenceController(context));
        controllers.add(new StorageItemPreferenceController(context, "pref_photos_videos"));
        controllers.add(new StorageItemPreferenceController(context, "pref_music_audio"));
        controllers.add(new StorageItemPreferenceController(context, "pref_games"));
        controllers.add(new StorageItemPreferenceController(context, "pref_other_apps"));
        controllers.add(new StorageItemPreferenceController(context, "pref_system"));
        controllers.add(new StorageItemPreferenceController(context, "pref_files"));
        return controllers;
    }

+115 −21
Original line number Diff line number Diff line
@@ -16,23 +16,48 @@

package com.android.settings.deviceinfo.storage;

import android.app.Fragment;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
import android.support.v7.preference.Preference;
import android.util.Log;

import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.Utils;
import com.android.settings.applications.ManageApplications;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;


/**
 * StorageItemPreferenceController handles the updating of a single storage preference line item.
 * StorageItemPreferenceController handles the storage line items which summarize the storage
 * categorization breakdown.
 */
public class StorageItemPreferenceController extends PreferenceController {
    private static final long NOT_YET_SET = -1;
    private final String mKey;
    private long mStorageSize;
    private static final String TAG = "StorageItemPreference";
    private final Fragment mFragment;
    private final StorageVolumeProvider mSvp;
    private VolumeInfo mVolume;
    private final int mUserId;

    private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";

    public StorageItemPreferenceController(Context context, String key) {
    public StorageItemPreferenceController(Context context, Fragment hostFragment,
            VolumeInfo volume, StorageVolumeProvider svp) {
        super(context);
        mKey = key;
        mStorageSize = NOT_YET_SET;
        mFragment = hostFragment;
        mVolume = volume;
        mSvp = svp;

        UserManager um = mContext.getSystemService(UserManager.class);
        mUserId = um.getUserHandle();
    }

    @Override
@@ -42,28 +67,97 @@ public class StorageItemPreferenceController extends PreferenceController {

    @Override
    public boolean handlePreferenceTreeClick(Preference preference) {
        if (preference == null) {
            return false;
        }

    @Override
    public String getPreferenceKey() {
        return mKey;
        // TODO: Currently, this reflects the existing behavior for these toggles.
        //       After the intermediate views are built, swap them in.
        Intent intent = null;
        switch (preference.getKey()) {
            case "pref_photos_videos":
                intent = getPhotosIntent();
                break;
            case "pref_music_audio":
                intent = getAudioIntent();
                break;
            case "pref_games":
                // TODO: Once app categorization is added, make this section.
            case "pref_other_apps":
                // Because we are likely constructed with a null volume, this is theoretically
                // possible.
                if (mVolume == null) {
                    break;
                }
                intent = getAppsIntent();
                break;
            case "pref_files":
                intent = getFilesIntent();
                break;
        }

    @Override
    public void updateState(Preference preference) {
        if (preference == null || mStorageSize == NOT_YET_SET) {
            return;
        if (intent != null) {
            intent.putExtra(Intent.EXTRA_USER_ID, mUserId);

            launchIntent(intent);
            return true;
        }

        return super.handlePreferenceTreeClick(preference);
    }

        StorageItemPreferenceAlternate summary = (StorageItemPreferenceAlternate) preference;
        summary.setStorageSize(mStorageSize);
    @Override
    public String getPreferenceKey() {
        return null;
    }

    /**
     * Sets the amount of bytes used by this storage item.
     * Sets the storage volume to use for when handling taps.
     */
    public void setStorageSize(long size) {
        mStorageSize = size;
    public void setVolume(VolumeInfo volume) {
        mVolume = volume;
    }

    private Intent getPhotosIntent() {
        Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
        intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "images_root"));
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        return intent;
    }

    private Intent getAudioIntent() {
        Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
        intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"));
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        return intent;
    }

    private Intent getAppsIntent() {
        Bundle args = new Bundle();
        args.putString(ManageApplications.EXTRA_CLASSNAME,
                Settings.StorageUseActivity.class.getName());
        args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
        args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
        return Utils.onBuildStartFragmentIntent(mContext,
                ManageApplications.class.getName(), args, null, R.string.apps_storage, null,
                false);
    }

    private Intent getFilesIntent() {
        return mSvp.findEmulatedForPrivate(mVolume).buildBrowseIntent();
    }

    private void launchIntent(Intent intent) {
        try {
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);

            if (userId == -1) {
                mFragment.startActivity(intent);
            } else {
                mFragment.getActivity().startActivityAsUser(intent, new UserHandle(userId));
            }
        } catch (ActivityNotFoundException e) {
            Log.w(TAG, "No activity found for " + intent);
        }
    }
}
+86 −20
Original line number Diff line number Diff line
@@ -17,63 +17,129 @@ package com.android.settings.deviceinfo.storage;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Fragment;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.content.Intent;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;

import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.SubSettings;
import com.android.settings.TestConfig;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.applications.ManageApplications;
import com.android.settingslib.deviceinfo.StorageVolumeProvider;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class StorageItemPreferenceControllerTest {
    private static final String KEY = "pref";
    private Context mContext;
    private VolumeInfo mVolume;
    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    private Fragment mFragment;
    @Mock
    private StorageVolumeProvider mSvp;
    private StorageItemPreferenceController mController;
    private PreferenceViewHolder mHolder;
    private StorageItemPreferenceAlternate mPreference;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        mVolume = new VolumeInfo("id", 0, null, "id");
        mContext = RuntimeEnvironment.application;
        mController = new StorageItemPreferenceController(mContext, KEY);
        mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp);
        mPreference = new StorageItemPreferenceAlternate(mContext);

        // Inflate the preference and the widget.
        LayoutInflater inflater = LayoutInflater.from(mContext);
        final View view = inflater.inflate(mPreference.getLayoutResource(),
                new LinearLayout(mContext), false);
        inflater.inflate(mPreference.getLayoutResource(), new LinearLayout(mContext), false);
    }

        mHolder = new PreferenceViewHolder(view);
    @Test
    public void testUpdateStateWithInitialState() {
        assertThat(mPreference.getSummary().toString()).isEqualTo(
                mContext.getString(R.string.memory_calculating_size));
    }

    @Test
    public void testGetKey() {
        assertThat(mController.getPreferenceKey()).isEqualTo(KEY);
    public void testClickPhotos() {
        mPreference.setKey("pref_photos_videos");
        mController.handlePreferenceTreeClick(mPreference);

        final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
                any(UserHandle.class));

        Intent intent = argumentCaptor.getValue();
        assertThat(intent.getAction()).isEqualTo(DocumentsContract.ACTION_BROWSE);
        assertThat(intent.getData()).isEqualTo(DocumentsContract.buildRootUri(
                "com.android.providers.media.documents",
                "images_root"));
    }

    @Test
    public void testUpdateStateWithInitialState() {
        mController.updateState(mPreference);
        assertThat(mPreference.getSummary().toString()).isEqualTo("Calculating…");
    public void testClickAudio() {
        mPreference.setKey("pref_music_audio");
        mController.handlePreferenceTreeClick(mPreference);

        final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
                any(UserHandle.class));

        Intent intent = argumentCaptor.getValue();
        assertThat(intent.getAction()).isEqualTo(DocumentsContract.ACTION_BROWSE);
        assertThat(intent.getData()).isEqualTo(DocumentsContract.buildRootUri(
                "com.android.providers.media.documents",
                "audio_root"));
    }

    @Test
    public void testPreferenceShouldUpdateAfterPopulatingData() {
        mController.setStorageSize(1024L);
        mController.updateState(mPreference);
        assertThat(mPreference.getSummary().toString()).isEqualTo("1.00KB");
    public void testClickApps() {
        mPreference.setKey("pref_other_apps");
        mController.handlePreferenceTreeClick(mPreference);

        final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
                any(UserHandle.class));

        Intent intent = argumentCaptor.getValue();
        assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
        assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
        assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
                ManageApplications.class.getName());
    }

    @Test
    public void testClickFiles() {
        when(mSvp.findEmulatedForPrivate(any(VolumeInfo.class))).thenReturn(mVolume);
        mPreference.setKey("pref_files");
        mController.handlePreferenceTreeClick(mPreference);

        final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
                any(UserHandle.class));

        Intent intent = argumentCaptor.getValue();
        Intent browseIntent = mVolume.buildBrowseIntent();
        assertThat(intent.getAction()).isEqualTo(browseIntent.getAction());
        assertThat(intent.getData()).isEqualTo(browseIntent.getData());
    }
}
 No newline at end of file