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

Commit ee7da79f authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Automerger Merge Worker
Browse files

Allow user to block individual apps from resuming. am: 48ce5892

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/12392268

Change-Id: I131ff7c33871d858a63824fc17ba168ba590f6e2
parents ef7b3433 48ce5892
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -12158,15 +12158,17 @@
    <!-- Title for media control settings [CHAR LIMIT=50]-->
    <string name="media_controls_title">Media</string>
    <!-- Summary for media control settings [CHAR LIMIT=60]-->
    <string name="media_controls_summary">Hide player when the media session has ended</string>
    <string name="media_controls_summary">Media player in Quick Settings</string>
    <!-- Description of toggle to enable or disable the media resumption feature in quick settings [CHAR LIMIT=NONE]-->
    <string name="media_controls_resume_description">The player allows you to resume a session from the expanded Quick Settings panel.</string>
    <string name="media_controls_resume_description">Show media player for an extended period to easily resume playback</string>
    <!-- Subtext for media settings when the player will be hidden [CHAR LIMIT=50] -->
    <string name="media_controls_hide_player">Hide player</string>
    <!-- Subtext for media settings when the player will be shown [CHAR LIMIT=50] -->
    <string name="media_controls_show_player">Show player</string>
    <!-- Subtext for media settings when no players can be shown [CHAR LIMIT=50] -->
    <string name="media_controls_no_players">No players available</string>
    <!-- Subtitle for section of media control settings that shows which apps are allowed [CHAR LIMIT=50] -->
    <string name="media_controls_apps_title">Allowed apps</string>
    <!-- Keywords for the media controls setting [CHAR LIMIT=NONE]-->
    <string name="keywords_media_controls">media</string>
</resources>
+5 −0
Original line number Diff line number Diff line
@@ -28,4 +28,9 @@
        app:controller="com.android.settings.sound.MediaControlsPreferenceController"
        app:allowDividerAbove="true" />

    <PreferenceCategory
        android:key="media_controls_resumable_apps"
        android:title="@string/media_controls_apps_title"
        app:controller="com.android.settings.sound.ResumableMediaAppsController" />

</PreferenceScreen>
+2 −2
Original line number Diff line number Diff line
@@ -35,12 +35,12 @@ public class MediaControlsPreferenceController extends TogglePreferenceControlle
    @Override
    public boolean isChecked() {
        int val = Settings.Secure.getInt(mContext.getContentResolver(), MEDIA_CONTROLS_RESUME, 1);
        return val == 0;
        return val == 1;
    }

    @Override
    public boolean setChecked(boolean isChecked) {
        int val = isChecked ? 0 : 1;
        int val = isChecked ? 1 : 0;
        return Settings.Secure.putInt(mContext.getContentResolver(), MEDIA_CONTROLS_RESUME, val);
    }

+138 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.sound;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
import android.service.media.MediaBrowserService;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;

import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;

import com.android.settings.core.BasePreferenceController;

import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Section of media controls settings that contains a list of potentially resumable apps
 */
public class ResumableMediaAppsController extends BasePreferenceController {
    private static final String TAG = "ResumableMediaAppsCtrl";

    private PreferenceGroup mPreferenceGroup;
    private PackageManager mPackageManager;
    private List<ResolveInfo> mResumeInfo;

    public ResumableMediaAppsController(Context context, String key) {
        super(context, key);
        mPackageManager = mContext.getPackageManager();
        Intent serviceIntent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
        mResumeInfo = mPackageManager.queryIntentServices(serviceIntent, 0);
    }

    @Override
    public int getAvailabilityStatus() {
        // Update list, since this will be called when the app goes to onStart / onPause
        Intent serviceIntent = new Intent(MediaBrowserService.SERVICE_INTERFACE);
        mResumeInfo = mPackageManager.queryIntentServices(serviceIntent, 0);
        return (mResumeInfo.size() > 0) ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        mPreferenceGroup = screen.findPreference(getPreferenceKey());
        Set<String> blockedApps = getBlockedMediaApps();
        for (ResolveInfo inf : mResumeInfo) {
            String packageName = inf.getComponentInfo().packageName;
            MediaSwitchPreference pref = new MediaSwitchPreference(mContext, packageName);
            CharSequence appTitle = packageName;
            try {
                appTitle = mPackageManager.getApplicationLabel(
                        mPackageManager.getApplicationInfo(packageName, 0));
                Drawable appIcon = mPackageManager.getApplicationIcon(packageName);
                pref.setIcon(appIcon);
            } catch (PackageManager.NameNotFoundException e) {
                Log.e(TAG, "Couldn't get app title", e);
            }
            pref.setTitle(appTitle);

            pref.setOnPreferenceChangeListener((preference, status) -> {
                MediaSwitchPreference mediaPreference = (MediaSwitchPreference) preference;
                boolean isEnabled = (boolean) status;
                Log.d(TAG, "preference " + mediaPreference + " changed " + isEnabled);

                if (isEnabled) {
                    blockedApps.remove(mediaPreference.getPackageName());
                } else {
                    blockedApps.add(mediaPreference.getPackageName());
                }
                setBlockedMediaApps(blockedApps);
                return true;
            });

            pref.setChecked(!blockedApps.contains(packageName));
            mPreferenceGroup.addPreference(pref);
        }
    }

    class MediaSwitchPreference extends SwitchPreference {
        private String mPackageName;

        MediaSwitchPreference(Context context, String packageName) {
            super(context);
            mPackageName = packageName;
        }

        public String getPackageName() {
            return mPackageName;
        }
    }

    private Set<String> getBlockedMediaApps() {
        String list = Settings.Secure.getString(mContext.getContentResolver(),
                Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED);
        if (TextUtils.isEmpty(list)) {
            return new ArraySet<>();
        }
        String[] names = list.split(":");
        Set<String> set = new ArraySet<>(names.length);
        Collections.addAll(set, names);
        return set;
    }

    private void setBlockedMediaApps(Set<String> apps) {
        if (apps == null || apps.size() == 0) {
            Settings.Secure.putString(mContext.getContentResolver(),
                    Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED, "");
            return;
        }
        String list = String.join(":", apps);
        Settings.Secure.putString(mContext.getContentResolver(),
                Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED, list);
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -69,26 +69,26 @@ public class MediaControlsPreferenceControllerTest {
    }

    @Test
    public void setChecked_enable_shouldTurnOff() {
    public void setChecked_enable_shouldTurnOn() {
        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1);
        Settings.Secure.putInt(mContentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 1);

        assertThat(mController.isChecked()).isFalse();
        assertThat(mController.isChecked()).isTrue();

        mController.setChecked(true);
        mController.setChecked(false);

        assertThat(Settings.Secure.getInt(mContentResolver,
                Settings.Secure.MEDIA_CONTROLS_RESUME, -1)).isEqualTo(0);
    }

    @Test
    public void setChecked_disable_shouldTurnOn() {
    public void setChecked_disable_shouldTurnOff() {
        Settings.Global.putInt(mContentResolver, Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1);
        Settings.Secure.putInt(mContentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 0);

        assertThat(mController.isChecked()).isTrue();
        assertThat(mController.isChecked()).isFalse();

        mController.setChecked(false);
        mController.setChecked(true);

        assertThat(Settings.Secure.getInt(mContentResolver,
                Settings.Secure.MEDIA_CONTROLS_RESUME, -1)).isEqualTo(1);
Loading