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

Commit b15cc090 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

Game Driver: Add SwitchBar to control GUP feature

Uncheck the global switch will hide the preference controllers and force
all apps to use system graphics driver. This change also add a content
observer to notify all the preference controllers of settings global
changes.

Bug: 119221883
Test: make RunSettingsRoboTests
Change-Id: Ice9ded17c759791a3728c552f79881e2215ac081
Merged-In: Ice9ded17c759791a3728c552f79881e2215ac081
parent 75548c4a
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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.development.gup;

import android.content.ContentResolver;
import android.database.ContentObserver;
import android.os.Handler;
import android.provider.Settings;

import androidx.annotation.VisibleForTesting;

/**
 * Helper class to observe Game Driver settings global change.
 */
public class GameDriverContentObserver extends ContentObserver {
    interface OnGameDriverContentChangedListener {
        void onGameDriverContentChanged();
    }

    @VisibleForTesting
    OnGameDriverContentChangedListener mListener;

    public GameDriverContentObserver(Handler handler, OnGameDriverContentChangedListener listener) {
        super(handler);
        mListener = listener;
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        mListener.onGameDriverContentChanged();
    }

    public void register(ContentResolver contentResolver) {
        contentResolver.registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.GUP_DEV_ALL_APPS), false, this);
    }

    public void unregister(ContentResolver contentResolver) {
        contentResolver.unregisterContentObserver(this);
    }
}
+19 −1
Original line number Diff line number Diff line
@@ -17,14 +17,20 @@
package com.android.settings.development.gup;

import android.content.Context;
import android.os.Bundle;

import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.SwitchBarController;

import java.util.List;

/**
 * Dashboard for Game Driver preferences.
 */
public class GupDashboard extends DashboardFragment {
    private static final String TAG = "GupDashboard";

@@ -47,4 +53,16 @@ public class GupDashboard extends DashboardFragment {
    public int getHelpResource() {
        return 0;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        final SettingsActivity activity = (SettingsActivity) getActivity();
        final SwitchBar switchBar = activity.getSwitchBar();
        final GupGlobalSwitchBarController switchBarController =
                new GupGlobalSwitchBarController(activity, new SwitchBarController(switchBar));
        getLifecycle().addObserver(switchBarController);
        switchBar.show();
    }
}
+47 −10
Original line number Diff line number Diff line
@@ -18,55 +18,92 @@ package com.android.settings.development.gup;

import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;

import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

public class GupEnableForAllAppsPreferenceController
        extends BasePreferenceController implements Preference.OnPreferenceChangeListener {
/**
 * Controller of global switch to enable Game Driver for all Apps.
 */
public class GupEnableForAllAppsPreferenceController extends BasePreferenceController
        implements Preference.OnPreferenceChangeListener,
                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
                   OnStart, OnStop {
    public static final int GUP_DEFAULT = 0;
    public static final int GUP_ALL_APPS = 1;
    public static final int GUP_OFF = 2;

    private final Context mContext;
    private final ContentResolver mContentResolver;
    @VisibleForTesting
    GameDriverContentObserver mGameDriverContentObserver;

    private SwitchPreference mPreference;

    public GupEnableForAllAppsPreferenceController(Context context, String key) {
        super(context, key);
        mContext = context;
        mContentResolver = context.getContentResolver();
        mGameDriverContentObserver =
                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
    }

    @Override
    public int getAvailabilityStatus() {
        return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
                        && (Settings.Global.getInt(
                                    mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                                != GUP_OFF)
                ? AVAILABLE
                : DISABLED_DEPENDENT_SETTING;
                : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        final SwitchPreference switchPreference =
                (SwitchPreference) screen.findPreference(getPreferenceKey());
        if (switchPreference == null) {
            return;
        mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
    }

    @Override
    public void onStart() {
        mGameDriverContentObserver.register(mContentResolver);
    }

    @Override
    public void onStop() {
        mGameDriverContentObserver.unregister(mContentResolver);
    }

    @Override
    public void updateState(Preference preference) {
        final SwitchPreference switchPreference = (SwitchPreference) preference;
        switchPreference.setVisible(isAvailable());
        switchPreference.setChecked(Settings.Global.getInt(mContentResolver,
                                            Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                == GUP_ALL_APPS);
        switchPreference.setOnPreferenceChangeListener(this);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        // When developer option is present, always overwrite GUP_DEV_ALL_APPS.
        Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS,
                (boolean) newValue ? GUP_ALL_APPS : GUP_DEFAULT);

        return true;
    }

    @Override
    public void onGameDriverContentChanged() {
        updateState(mPreference);
    }
}
+98 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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.development.gup;

import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_ALL_APPS;
import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;

import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.VisibleForTesting;

import com.android.settings.widget.SwitchWidgetController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

/**
 * Controller of global switch bar used to fully turn off Game Driver.
 */
public class GupGlobalSwitchBarController
        implements SwitchWidgetController.OnSwitchChangeListener,
                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
                   OnStart, OnStop {
    private final Context mContext;
    private final ContentResolver mContentResolver;
    @VisibleForTesting
    SwitchWidgetController mSwitchWidgetController;
    @VisibleForTesting
    GameDriverContentObserver mGameDriverContentObserver;

    GupGlobalSwitchBarController(Context context, SwitchWidgetController switchWidgetController) {
        mContext = context;
        mContentResolver = context.getContentResolver();
        mGameDriverContentObserver =
                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);
        mSwitchWidgetController = switchWidgetController;
        mSwitchWidgetController.setEnabled(
                DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context));
        mSwitchWidgetController.setChecked(Settings.Global.getInt(mContentResolver,
                                                   Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                != GUP_OFF);
        mSwitchWidgetController.setListener(this);
    }

    @Override
    public void onStart() {
        mSwitchWidgetController.startListening();
        mGameDriverContentObserver.register(mContentResolver);
    }

    @Override
    public void onStop() {
        mSwitchWidgetController.stopListening();
        mGameDriverContentObserver.unregister(mContentResolver);
    }

    @Override
    public boolean onSwitchToggled(boolean isChecked) {
        if (!isChecked) {
            Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_OFF);
            return true;
        }

        if (Settings.Global.getInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                != GUP_ALL_APPS) {
            Settings.Global.putInt(mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT);
        }

        return true;
    }

    @Override
    public void onGameDriverContentChanged() {
        mSwitchWidgetController.setChecked(Settings.Global.getInt(mContentResolver,
                                                   Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                != GUP_OFF);
    }
}
+71 −19
Original line number Diff line number Diff line
@@ -16,11 +16,16 @@

package com.android.settings.development.gup;

import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_DEFAULT;
import static com.android.settings.development.gup.GupEnableForAllAppsPreferenceController.GUP_OFF;

import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.VisibleForTesting;
@@ -31,6 +36,9 @@ import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.development.DevelopmentSettingsEnabler;

import java.text.Collator;
@@ -42,21 +50,37 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class GupPreferenceController
        extends BasePreferenceController implements Preference.OnPreferenceChangeListener {
/**
 * Controller of all the per App based list preferences.
 */
public class GupPreferenceController extends BasePreferenceController
        implements Preference.OnPreferenceChangeListener,
                   GameDriverContentObserver.OnGameDriverContentChangedListener, LifecycleObserver,
                   OnStart, OnStop {
    private final Context mContext;
    private final ContentResolver mContentResolver;
    private final CharSequence[] mEntryList;
    private final String mPreferenceTitle;
    private final String mPreferenceDefault;
    private final String mPreferenceGup;
    private final String mPreferenceSystem;
    @VisibleForTesting
    GameDriverContentObserver mGameDriverContentObserver;

    private final List<AppInfo> mAppInfos;
    private final Set<String> mDevOptInApps;
    private final Set<String> mDevOptOutApps;

    private PreferenceGroup mPreferenceGroup;

    public GupPreferenceController(Context context, String key) {
        super(context, key);

        mContext = context;
        mContentResolver = context.getContentResolver();
        mGameDriverContentObserver =
                new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this);

        final Resources resources = context.getResources();
        mEntryList = resources.getStringArray(R.array.gup_app_preference_values);
        mPreferenceTitle = resources.getString(R.string.gup_app_preference_title);
@@ -68,35 +92,57 @@ public class GupPreferenceController
        // Update the UI when all the app infos are ready.
        mAppInfos = getAppInfos(context);

        final ContentResolver contentResolver = context.getContentResolver();
        mDevOptInApps =
                getGlobalSettingsString(contentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS);
                getGlobalSettingsString(mContentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS);
        mDevOptOutApps =
                getGlobalSettingsString(contentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS);
                getGlobalSettingsString(mContentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS);
    }

    @Override
    public int getAvailabilityStatus() {
        return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
                        && (Settings.Global.getInt(
                                    mContentResolver, Settings.Global.GUP_DEV_ALL_APPS, GUP_DEFAULT)
                                != GUP_OFF)
                ? AVAILABLE
                : DISABLED_DEPENDENT_SETTING;
                : CONDITIONALLY_UNAVAILABLE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
        super.displayPreference(screen);
        final PreferenceGroup preferenceGroup =
                (PreferenceGroup) screen.findPreference(getPreferenceKey());
        if (preferenceGroup == null) {
            return;
        }
        mPreferenceGroup = (PreferenceGroup) screen.findPreference(getPreferenceKey());

        final Context context = mPreferenceGroup.getContext();
        for (AppInfo appInfo : mAppInfos) {
            preferenceGroup.addPreference(
                    createListPreference(appInfo.info.packageName, appInfo.label));
            mPreferenceGroup.addPreference(
                    createListPreference(context, appInfo.info.packageName, appInfo.label));
        }
    }

    @Override
    public void onStart() {
        mGameDriverContentObserver.register(mContentResolver);
    }

    @Override
    public void onStop() {
        mGameDriverContentObserver.unregister(mContentResolver);
    }

    @Override
    public void updateState(Preference preference) {
        // This is a workaround, because PreferenceGroup.setVisible is not applied to the
        // preferences inside the group.
        final boolean isGroupAvailable = isAvailable();
        final PreferenceGroup group = (PreferenceGroup) preference;
        for (int idx = 0; idx < group.getPreferenceCount(); idx++) {
            final Preference pref = group.getPreference(idx);
            pref.setVisible(isGroupAvailable);
        }
        preference.setVisible(isGroupAvailable);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        final ListPreference listPref = (ListPreference) preference;
@@ -120,14 +166,19 @@ public class GupPreferenceController

        // Push the updated Sets for opt-in and opt-out apps to
        // corresponding Settings.Global.GUP_DEV_OPT_(IN|OUT)_APPS
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.GUP_DEV_OPT_IN_APPS, String.join(",", mDevOptInApps));
        Settings.Global.putString(mContext.getContentResolver(),
                Settings.Global.GUP_DEV_OPT_OUT_APPS, String.join(",", mDevOptOutApps));
        Settings.Global.putString(mContentResolver, Settings.Global.GUP_DEV_OPT_IN_APPS,
                String.join(",", mDevOptInApps));
        Settings.Global.putString(mContentResolver, Settings.Global.GUP_DEV_OPT_OUT_APPS,
                String.join(",", mDevOptOutApps));

        return true;
    }

    @Override
    public void onGameDriverContentChanged() {
        updateState(mPreferenceGroup);
    }

    // AppInfo class to achieve loading the application label only once
    class AppInfo {
        AppInfo(PackageManager packageManager, ApplicationInfo applicationInfo) {
@@ -176,8 +227,9 @@ public class GupPreferenceController
    };

    @VisibleForTesting
    protected ListPreference createListPreference(String packageName, String appName) {
        final ListPreference listPreference = new ListPreference(mContext);
    protected ListPreference createListPreference(
            Context context, String packageName, String appName) {
        final ListPreference listPreference = new ListPreference(context);

        listPreference.setKey(packageName);
        listPreference.setTitle(appName);
Loading