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

Commit d1172942 authored by Daniel Nishi's avatar Daniel Nishi Committed by Android (Google) Code Review
Browse files

Merge "Add a music apps view to the Storage Settings."

parents 58f72953 31027dae
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -8165,6 +8165,11 @@
    <!-- Title of games app storage screen [CHAR LIMIT=30] -->
    <string name="game_storage_settings">Games</string>
    <!-- Title for audio files preference. [CHAR LIMIT=50] -->
    <string name="audio_files_title">Audio files</string>
    <!-- Title for the Audio storage view. [CHAR LIMIT=50] -->
    <string name="audio_storage_title">Music</string>
    <!-- UI webview setting: WebView uninstalled-for-user explanatory text [CHAR LIMIT=30] -->
    <string name="webview_uninstalled_for_user">Uninstalled for user <xliff:g id="user" example="John Doe">%s</xliff:g>\n</string>
    <!-- UI webview setting: WebView disabled-for-user explanatory text [CHAR LIMIT=30] -->
+21 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.app.Fragment;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -1224,4 +1225,24 @@ public final class Utils extends com.android.settingslib.Utils {
            return null;
        }
    }

    /**
     * Launches an intent which may optionally have a user id defined.
     * @param fragment Fragment to use to launch the activity.
     * @param intent Intent to launch.
     */
    public static void launchIntent(Fragment fragment, Intent intent) {
        try {
            final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);

            if (userId == -1) {
                fragment.startActivity(intent);
            } else {
                fragment.getActivity().startActivityAsUser(intent, new UserHandle(userId));
            }
        } catch (ActivityNotFoundException e) {
            Log.w(TAG, "No activity found for " + intent);
        }
    }

}
+48 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.settings.applications;

import android.app.Fragment;
import android.view.View;

/**
 * FileViewHolderController handles adapting the AppViewHolder to work as a general purpose
 * storage categorization preference in the ManageApplications view.
 */
public interface FileViewHolderController {
    /**
     * Begins a synchronous query for statistics for the files.
     */
    void queryStats();

    /**
     * Returns if the preference should be shown.
     */
    boolean shouldShow();

    /**
     * Initializes the view within an AppViewHolder.
     * @param holder The holder to use to initialize.
     */
    void setupView(AppViewHolder holder);

    /**
     * Handles the behavior when the view is clicked.
     * @param fragment Fragment where the click originated.
     */
    void onClick(Fragment fragment);
}
+91 −25
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.settings.applications;

import android.app.Activity;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
@@ -32,6 +33,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceFrameLayout;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -71,6 +73,7 @@ import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsSt
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.deviceinfo.storage.StorageStatsSource;
import com.android.settings.fuelgauge.HighPowerDetail;
import com.android.settings.fuelgauge.PowerWhitelistBackend;
import com.android.settings.notification.AppNotificationSettings;
@@ -108,6 +111,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
    // Used for storage only.
    public static final String EXTRA_VOLUME_UUID = "volumeUuid";
    public static final String EXTRA_VOLUME_NAME = "volumeName";
    public static final String EXTRA_STORAGE_TYPE = "storageType";

    private static final String EXTRA_SORT_ORDER = "sortOrder";
    private static final String EXTRA_SHOW_SYSTEM = "showSystem";
@@ -140,6 +144,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
    public static final int FILTER_APPS_WRITE_SETTINGS = 10;
    public static final int FILTER_APPS_INSTALL_SOURCES = 12;

    // Storage types. Used to determine what the extra item in the list of preferences is.
    public static final int STORAGE_TYPE_DEFAULT = 0;
    public static final int STORAGE_TYPE_MUSIC = 1;

    // This is the string labels for the filter modes above, the order must be kept in sync.
    public static final int[] FILTER_LABELS = new int[]{
            R.string.high_power_filter_on, // High power whitelist, on
@@ -227,6 +235,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
    private ResetAppsHelper mResetAppsHelper;
    private String mVolumeUuid;
    private String mVolumeName;
    private int mStorageType;

    @Override
    public void onCreate(Bundle savedInstanceState) {
@@ -250,6 +259,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
            if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
                mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
                mVolumeName = args.getString(EXTRA_VOLUME_NAME);
                mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
                mListType = LIST_TYPE_STORAGE;
            } else {
                // No volume selected, display a normal list, sorted by size.
@@ -316,6 +326,13 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                mApplications.mHasReceivedBridgeCallback =
                        savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
            }
            if (mStorageType == STORAGE_TYPE_MUSIC) {
                Context context = getContext();
                mApplications.setExtraViewController(new MusicViewHolderController(
                        context,
                        new StorageStatsSource(context),
                        mVolumeUuid));
            }
            mListView.setAdapter(mApplications);
            mListView.setRecyclerListener(mApplications);
            mListView.setFastScrollEnabled(isFastScrollEnabled());
@@ -361,7 +378,11 @@ public class ManageApplications extends InstrumentedPreferenceFragment
            mFilterAdapter.enableFilter(FILTER_APPS_POWER_WHITELIST_ALL);
        }
        if (mListType == LIST_TYPE_STORAGE) {
            mApplications.setOverrideFilter(new VolumeFilter(mVolumeUuid));
            AppFilter filter = new VolumeFilter(mVolumeUuid);
            if (mStorageType == STORAGE_TYPE_MUSIC) {
                filter = new CompoundFilter(ApplicationsState.FILTER_AUDIO, filter);
            }
            mApplications.setOverrideFilter(filter);
        }
        if (mListType == LIST_TYPE_GAMES) {
            mApplications.setOverrideFilter(ApplicationsState.FILTER_GAMES);
@@ -626,11 +647,17 @@ public class ManageApplications extends InstrumentedPreferenceFragment

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        if (mApplications != null && mApplications.getCount() > position) {
        if (mApplications == null) {
            return;
        }

        if (mApplications.getApplicationCount() > position) {
            ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
            mCurrentPkgName = entry.info.packageName;
            mCurrentUid = entry.info.uid;
            startApplicationDetailsActivity();
        } else {
            mApplications.mExtraViewController.onClick(this);
        }
    }

@@ -769,6 +796,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
        private AppFilter mOverrideFilter;
        private boolean mHasReceivedLoadEntries;
        private boolean mHasReceivedBridgeCallback;
        private FileViewHolderController mExtraViewController;

        // These two variables are used to remember and restore the last scroll position when this
        // fragment is paused. We need this special handling because app entries are added gradually
@@ -839,6 +867,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
            rebuild(true);
        }

        public void setExtraViewController(FileViewHolderController extraViewController) {
            mExtraViewController = extraViewController;
        }

        public void resume(int sort) {
            if (DEBUG) Log.i(TAG, "Resume!  mResumed=" + mResumed);
            if (!mResumed) {
@@ -889,7 +921,6 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                // Don't rebuild the list until all the app entries are loaded.
                return;
            }
            if (DEBUG) Log.i(TAG, "Rebuilding app list...");
            ApplicationsState.AppFilter filterObj;
            Comparator<AppEntry> comparatorObj;
            boolean emulated = Environment.isExternalStorageEmulated();
@@ -924,8 +955,12 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                    comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
                    break;
            }
            filterObj = new CompoundFilter(filterObj, ApplicationsState.FILTER_NOT_HIDE);

            if (mExtraViewController != null) {
                mExtraViewController.queryStats();
            }

            filterObj = new CompoundFilter(filterObj, ApplicationsState.FILTER_NOT_HIDE);
            AppFilter finalFilterObj = filterObj;
            mBgHandler.post(() -> {
                final ArrayList<AppEntry> entries = mSession.rebuild(finalFilterObj,
@@ -1104,6 +1139,10 @@ public class ManageApplications extends InstrumentedPreferenceFragment
        public void onPackageSizeChanged(String packageName) {
            for (int i = 0; i < mActive.size(); i++) {
                AppViewHolder holder = (AppViewHolder) mActive.get(i).getTag();
                ApplicationInfo info = holder.entry.info;
                if (info == null) {
                    continue;
                }
                if (holder.entry.info.packageName.equals(packageName)) {
                    synchronized (holder.entry) {
                        updateSummary(holder);
@@ -1136,10 +1175,22 @@ public class ManageApplications extends InstrumentedPreferenceFragment
        }

        public int getCount() {
            if (mEntries == null) {
                return 0;
            }
            int extraViewAddition =
                    (mExtraViewController != null && mExtraViewController.shouldShow()) ? 1 : 0;
            return mEntries.size() + extraViewAddition;
        }

        public int getApplicationCount() {
            return mEntries != null ? mEntries.size() : 0;
        }

        public Object getItem(int position) {
            if (position == mEntries.size()) {
                return mExtraViewController;
            }
            return mEntries.get(position);
        }

@@ -1148,6 +1199,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
        }

        public long getItemId(int position) {
            if (position == mEntries.size()) {
                return -1;
            }
            return mEntries.get(position).id;
        }

@@ -1158,6 +1212,11 @@ public class ManageApplications extends InstrumentedPreferenceFragment

        @Override
        public boolean isEnabled(int position) {
            if (position == mEntries.size() && mExtraViewController != null &&
                    mExtraViewController.shouldShow()) {
                return true;
            }

            if (mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
                return true;
            }
@@ -1172,6 +1231,11 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                    convertView);
            convertView = holder.rootView;

            // Handle the extra view if it is the last entry.
            if (mEntries != null && mExtraViewController != null && position == mEntries.size()) {
                mExtraViewController.setupView(holder);
                convertView.setEnabled(true);
            } else {
                // Bind the data efficiently with the holder
                ApplicationsState.AppEntry entry = mEntries.get(position);
                synchronized (entry) {
@@ -1194,9 +1258,11 @@ public class ManageApplications extends InstrumentedPreferenceFragment
                        holder.disabled.setVisibility(View.GONE);
                    }
                }
                convertView.setEnabled(isEnabled(position));
            }

            mActive.remove(convertView);
            mActive.add(convertView);
            convertView.setEnabled(isEnabled(position));
            return convertView;
        }

+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.settings.applications;

import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.provider.DocumentsContract;
import android.support.annotation.WorkerThread;
import android.text.format.Formatter;

import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.storage.StorageStatsSource;

/**
 * MusicViewHolderController controls an Audio/Music file view in the ManageApplications view.
 */
public class MusicViewHolderController implements FileViewHolderController {
    private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";

    private Context mContext;
    private StorageStatsSource mSource;
    private String mVolumeUuid;
    private long mMusicSize;

    public MusicViewHolderController(
            Context context, StorageStatsSource source, String volumeUuid) {
        mContext = context;
        mSource = source;
        mVolumeUuid = volumeUuid;
    }

    @Override
    @WorkerThread
    public void queryStats() {
        mMusicSize = mSource.getExternalStorageStats(mVolumeUuid, UserHandle.CURRENT).audioBytes;
    }

    @Override
    public boolean shouldShow() {
        return true;
    }

    @Override
    public void setupView(AppViewHolder holder) {
        holder.appIcon.setImageDrawable(mContext.getDrawable(R.drawable.empty_icon));
        holder.appName.setText(mContext.getText(R.string.audio_files_title));
        holder.summary.setText(Formatter.formatFileSize(mContext, mMusicSize));
    }

    @Override
    public void onClick(Fragment fragment) {
        Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
        intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"));
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.putExtra(Intent.EXTRA_USER_ID, UserHandle.CURRENT);
        Utils.launchIntent(fragment, intent);
    }
}
Loading