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

Commit bd9b0e42 authored by Robin Lee's avatar Robin Lee
Browse files

Add auto revoke support for Android TV

Test: atest android.os.cts.AutoRevokeTest
Bug: 158098457
Change-Id: I2df8d28ac68864a145f4cf7858b9cd01e44e46b5
parent 1e829af8
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ public final class ManagePermissionsActivity extends FragmentActivity {
                if (DeviceUtils.isAuto(this)) {
                    androidXFragment = AutoManageStandardPermissionsFragment.newInstance();
                } else if (DeviceUtils.isTelevision(this)) {
                    fragment =
                    androidXFragment =
                            com.android.permissioncontroller.permission.ui.television
                                    .ManagePermissionsFragment.newInstance();
                } else {
@@ -207,8 +207,8 @@ public final class ManagePermissionsActivity extends FragmentActivity {
                } else if (DeviceUtils.isWear(this)) {
                    androidXFragment = AppPermissionsFragmentWear.newInstance(packageName);
                } else if (DeviceUtils.isTelevision(this)) {
                    fragment = com.android.permissioncontroller.permission.ui.television
                            .AppPermissionsFragment.newInstance(packageName);
                    androidXFragment = com.android.permissioncontroller.permission.ui.television
                            .AppPermissionsFragment.newInstance(packageName, userHandle);
                } else {
                    Bundle args = AppPermissionGroupsFragment.createArgs(packageName, userHandle,
                            sessionId, true);
@@ -241,7 +241,7 @@ public final class ManagePermissionsActivity extends FragmentActivity {
                if (DeviceUtils.isAuto(this)) {
                    androidXFragment = AutoPermissionAppsFragment.newInstance(permissionName);
                } else if (DeviceUtils.isTelevision(this)) {
                    fragment = com.android.permissioncontroller.permission.ui.television
                    androidXFragment = com.android.permissioncontroller.permission.ui.television
                            .PermissionAppsFragment.newInstance(permissionName);
                } else {

+66 −11
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.Log;
@@ -37,19 +38,24 @@ import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import androidx.lifecycle.ViewModelProvider;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;

import com.android.permissioncontroller.R;
import com.android.permissioncontroller.permission.model.AppPermissionGroup;
import com.android.permissioncontroller.permission.model.AppPermissions;
import com.android.permissioncontroller.permission.model.livedatatypes.AutoRevokeState;
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModel;
import com.android.permissioncontroller.permission.ui.model.AppPermissionGroupsViewModelFactory;
import com.android.permissioncontroller.permission.ui.ReviewPermissionsActivity;
import com.android.permissioncontroller.permission.utils.LocationUtils;
import com.android.permissioncontroller.permission.utils.SafetyNetLogger;
import com.android.permissioncontroller.permission.utils.Utils;
import com.android.permissioncontroller.R;

public final class AppPermissionsFragment extends SettingsWithHeader
        implements OnPreferenceChangeListener {
@@ -57,22 +63,26 @@ public final class AppPermissionsFragment extends SettingsWithHeader
    private static final String LOG_TAG = "ManagePermsFragment";

    static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton";
    private static final String AUTO_REVOKE_SWITCH_KEY = "_AUTO_REVOKE_SWITCH_KEY";

    private static final int MENU_ALL_PERMS = 0;

    private ArraySet<AppPermissionGroup> mToggledGroups;
    private AppPermissionGroupsViewModel mViewModel;
    private AppPermissions mAppPermissions;
    private PreferenceScreen mExtraScreen;

    private boolean mHasConfirmedRevoke;

    public static AppPermissionsFragment newInstance(String packageName) {
        return setPackageName(new AppPermissionsFragment(), packageName);
    public static AppPermissionsFragment newInstance(String packageName, UserHandle user) {
        return setPackage(new AppPermissionsFragment(), packageName, user);
    }

    private static <T extends Fragment> T setPackageName(T fragment, String packageName) {
    private static <T extends PermissionsFrameFragment> T setPackage(
            T fragment, String packageName, UserHandle user) {
        Bundle arguments = new Bundle();
        arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName);
        arguments.putParcelable(Intent.EXTRA_USER, user);
        fragment.setArguments(arguments);
        return fragment;
    }
@@ -87,7 +97,9 @@ public final class AppPermissionsFragment extends SettingsWithHeader
            ab.setDisplayHomeAsUpEnabled(true);
        }

        String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
        final String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
        final UserHandle user = getArguments().getParcelable(Intent.EXTRA_USER);

        Activity activity = getActivity();
        PackageInfo packageInfo = getPackageInfo(activity, packageName);
        if (packageInfo == null) {
@@ -96,24 +108,30 @@ public final class AppPermissionsFragment extends SettingsWithHeader
            return;
        }


        mAppPermissions = new AppPermissions(activity, packageInfo, true,
                () -> getActivity().finish());

        if (mAppPermissions.isReviewRequired()) {
            Intent intent = new Intent(getActivity(), ReviewPermissionsActivity.class);
            intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
            intent.putExtra(Intent.EXTRA_USER, user);
            startActivity(intent);
            getActivity().finish();
            return;
        }

        loadPreferences();
    }

    @Override
    public void onResume() {
        super.onResume();
        final String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
        final UserHandle user = getArguments().getParcelable(Intent.EXTRA_USER);

        AppPermissionGroupsViewModelFactory factory =
                new AppPermissionGroupsViewModelFactory(packageName, user, 0);
        mViewModel = new ViewModelProvider(this, factory).get(AppPermissionGroupsViewModel.class);
        mViewModel.getAutoRevokeLiveData().observe(this, this::setAutoRevokeToggleState);

        mAppPermissions.refresh();
        loadPreferences();
        setPreferencesCheckedState();
@@ -128,7 +146,8 @@ public final class AppPermissionsFragment extends SettingsWithHeader
            }

            case MENU_ALL_PERMS: {
                Fragment frag = AllAppPermissionsFragment.newInstance(
                PermissionsFrameFragment frag =
                        AllAppPermissionsFragment.newInstance(
                                getArguments().getString(Intent.EXTRA_PACKAGE_NAME));
                getFragmentManager().beginTransaction()
                        .replace(android.R.id.content, frag)
@@ -224,10 +243,13 @@ public final class AppPermissionsFragment extends SettingsWithHeader
            }
        }

        final String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME);
        final UserHandle user = getArguments().getParcelable(Intent.EXTRA_USER);

        if (mExtraScreen != null) {
            extraPerms.setOnPreferenceClickListener(preference -> {
                AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment();
                setPackageName(frag, getArguments().getString(Intent.EXTRA_PACKAGE_NAME));
                setPackage(frag, packageName, user);
                frag.setTargetFragment(AppPermissionsFragment.this, 0);
                getFragmentManager().beginTransaction()
                        .replace(android.R.id.content, frag)
@@ -241,6 +263,8 @@ public final class AppPermissionsFragment extends SettingsWithHeader
            screen.addPreference(extraPerms);
        }

        addAutoRevokePreferences(getPreferenceScreen());

        setLoading(false /* loading */, true /* animate */);
    }

@@ -314,6 +338,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader

    @Override
    public void onPause() {
        mViewModel.getAutoRevokeLiveData().removeObservers(this);
        super.onPause();
        logToggledGroups();
    }
@@ -337,6 +362,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader
        if (mExtraScreen != null) {
            setPreferencesCheckedState(mExtraScreen);
        }
        setAutoRevokeToggleState(mViewModel.getAutoRevokeLiveData().getValue());
    }

    private void setPreferencesCheckedState(PreferenceScreen screen) {
@@ -353,6 +379,35 @@ public final class AppPermissionsFragment extends SettingsWithHeader
        }
    }


    private void addAutoRevokePreferences(PreferenceScreen screen) {
        SwitchPreference autoRevokeSwitch =
                new SwitchPreference(screen.getPreferenceManager().getContext());
        autoRevokeSwitch.setOnPreferenceClickListener((preference) -> {
            mViewModel.setAutoRevoke(autoRevokeSwitch.isChecked());
            android.util.Log.w(LOG_TAG, "setAutoRevoke " + autoRevokeSwitch.isChecked());
            return true;
        });
        autoRevokeSwitch.setTitle(R.string.auto_revoke_label);
        autoRevokeSwitch.setSummary(R.string.auto_revoke_summary);
        autoRevokeSwitch.setKey(AUTO_REVOKE_SWITCH_KEY);
        screen.addPreference(autoRevokeSwitch);
    }

    private void setAutoRevokeToggleState(AutoRevokeState state) {
        SwitchPreference autoRevokeSwitch = getPreferenceScreen().findPreference(
                AUTO_REVOKE_SWITCH_KEY);
        if (state == null || autoRevokeSwitch == null) {
            return;
        }
        if (!state.isEnabledGlobal() || !state.getShouldShowSwitch()) {
            autoRevokeSwitch.setVisible(false);
            return;
        }
        autoRevokeSwitch.setVisible(true);
        autoRevokeSwitch.setChecked(state.isEnabledForApp());
    }

    private static PackageInfo getPackageInfo(Activity activity, String packageName) {
        try {
            return activity.getPackageManager().getPackageInfo(
+4 −2
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@
package com.android.permissioncontroller.permission.ui.television;

import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
@@ -26,6 +25,8 @@ import android.view.MenuItem;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentTransaction;
import androidx.loader.app.LoaderManager;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceScreen;
@@ -63,7 +64,8 @@ public final class ManagePermissionsFragment extends SettingsWithHeader
        if (ab != null) {
            ab.setDisplayHomeAsUpEnabled(true);
        }
        mPermissions = new PermissionGroups(getContext(), getLoaderManager(), this, false, true);
        mPermissions = new PermissionGroups(
                getContext(), getActivity().getLoaderManager(), this, false, true);
    }

    @Override
+2 −1
Original line number Diff line number Diff line
@@ -59,7 +59,8 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements
        return setPermissionName(new PermissionAppsFragment(), permissionName);
    }

    private static <T extends Fragment> T setPermissionName(T fragment, String permissionName) {
    private static <T extends PermissionsFrameFragment> T setPermissionName(
            T fragment, String permissionName) {
        Bundle arguments = new Bundle();
        arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName);
        fragment.setArguments(arguments);
+2 −2
Original line number Diff line number Diff line
@@ -27,13 +27,13 @@ import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.leanback.widget.VerticalGridView;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;

import com.android.permissioncontroller.R;

public abstract class PermissionsFrameFragment extends PreferenceFragment {
public abstract class PermissionsFrameFragment extends PreferenceFragmentCompat {

    // Key identifying the preference used on TV as the extra header in a permission fragment.
    // This is to distinguish it from the rest of the preferences