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

Commit 05f85914 authored by Hani Kazmi's avatar Hani Kazmi
Browse files

Enable ECM restrictions for Usage Access and Device Admin

This commit continues the work to make all special app access
permissions ECM restrictable. Some implementation notes:

1. The FilterTouchesSwitchPreference and AppSwitchPrefernce components
   are replaced with RestrictedSwitchPreference. afaict this is a
   superset - it still filters out obscured touches and shows the app
   icon.

2. I'm treating this as mostly a refactoring, and so do not have a
   feature flag around most of the changes. Enabling ECM for them /is/
   behind the feature flag in RestrictedLockUtilsInternal.

3. app_ops_permissions_details.xml is currently only used by
   UsageAccessDetails.

Bug: 297372999
Test: Manually tested on device. Automated tests to follow
Change-Id: I65fe7ec099582de19192a77ad2e41c1558761502
parent ded1cd59
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto">

    <com.android.settings.widget.FilterTouchesSwitchPreference
    <com.android.settingslib.RestrictedSwitchPreference
        android:key="app_ops_settings_switch" />

    <com.android.settingslib.widget.FooterPreference
+12 −4
Original line number Diff line number Diff line
@@ -38,11 +38,11 @@ import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.TwoStatePreference;

import com.android.settings.R;
import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;

public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
@@ -57,7 +57,7 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
    // TODO: Break out this functionality into its own class.
    private AppStateUsageBridge mUsageBridge;
    private AppOpsManager mAppOpsManager;
    private TwoStatePreference mSwitchPref;
    private RestrictedSwitchPreference mSwitchPref;
    private Preference mUsageDesc;
    private Intent mSettingsIntent;
    private UsageState mUsageState;
@@ -78,7 +78,7 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
        mDpm = context.getSystemService(DevicePolicyManager.class);

        addPreferencesFromResource(R.xml.app_ops_permissions_details);
        mSwitchPref = (TwoStatePreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
        mSwitchPref = (RestrictedSwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
        mUsageDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);

        getPreferenceScreen().setTitle(R.string.usage_access);
@@ -170,8 +170,16 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
                mPackageInfo.applicationInfo.uid);

        boolean hasAccess = mUsageState.isPermissible();
        boolean shouldEnable = mUsageState.permissionDeclared;

        if (shouldEnable && !hasAccess) {
            mSwitchPref.checkEcmRestrictionAndSetDisabled(AppOpsManager.OPSTR_GET_USAGE_STATS,
                    mPackageName, mPackageInfo.applicationInfo.uid);
            shouldEnable = !mSwitchPref.isDisabledByEcm();
        }

        mSwitchPref.setChecked(hasAccess);
        mSwitchPref.setEnabled(mUsageState.permissionDeclared);
        mSwitchPref.setEnabled(shouldEnable);

        ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
                PackageManager.GET_META_DATA, mUserId);
+8 −0
Original line number Diff line number Diff line
@@ -86,6 +86,14 @@ class DeviceAdminListItem implements Comparable<DeviceAdminListItem> {
        return new UserHandle(getUserIdFromDeviceAdminInfo(mInfo));
    }

    public int getUid() {
        return mInfo.getActivityInfo().applicationInfo.uid;
    }

    public String getPackageName() {
        return mInfo.getPackageName();
    }

    public Intent getLaunchIntent(Context context) {
        return new Intent(context, DeviceAdminAdd.class)
                .putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mInfo.getComponent());
+13 −9
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.applications.specialaccess.deviceadmin;

import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;

import android.Manifest;
import android.app.AppGlobals;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DeviceAdminReceiver;
@@ -45,12 +46,13 @@ import androidx.preference.PreferenceScreen;

import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
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.widget.AppSwitchPreference;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.TwoTargetPreference;

import org.xmlpull.v1.XmlPullParserException;

@@ -167,35 +169,35 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
        if (mFooterPreference != null) {
            mFooterPreference.setVisible(mAdmins.isEmpty());
        }
        final Map<String, AppSwitchPreference> preferenceCache = new ArrayMap<>();
        final Map<String, RestrictedSwitchPreference> preferenceCache = new ArrayMap<>();
        final Context prefContext = mPreferenceGroup.getContext();
        final int childrenCount = mPreferenceGroup.getPreferenceCount();
        for (int i = 0; i < childrenCount; i++) {
            final Preference pref = mPreferenceGroup.getPreference(i);
            if (!(pref instanceof AppSwitchPreference)) {
            if (!(pref instanceof RestrictedSwitchPreference switchPref)) {
                continue;
            }
            final AppSwitchPreference appSwitch = (AppSwitchPreference) pref;
            preferenceCache.put(appSwitch.getKey(), appSwitch);
            preferenceCache.put(switchPref.getKey(), switchPref);
        }
        for (DeviceAdminListItem item : mAdmins) {
            final String key = item.getKey();
            AppSwitchPreference pref = preferenceCache.remove(key);
            RestrictedSwitchPreference pref = preferenceCache.remove(key);
            if (pref == null) {
                pref = new AppSwitchPreference(prefContext);
                pref = new RestrictedSwitchPreference(prefContext);
                mPreferenceGroup.addPreference(pref);
            }
            bindPreference(item, pref);
        }
        for (AppSwitchPreference unusedCacheItem : preferenceCache.values()) {
        for (RestrictedSwitchPreference unusedCacheItem : preferenceCache.values()) {
            mPreferenceGroup.removePreference(unusedCacheItem);
        }
    }

    private void bindPreference(DeviceAdminListItem item, AppSwitchPreference pref) {
    private void bindPreference(DeviceAdminListItem item, RestrictedSwitchPreference pref) {
        pref.setKey(item.getKey());
        pref.setTitle(item.getName());
        pref.setIcon(item.getIcon());
        pref.setIconSize(TwoTargetPreference.ICON_SIZE_DEFAULT);
        pref.setChecked(item.isActive());
        pref.setSummary(item.getDescription());
        pref.setEnabled(item.isEnabled());
@@ -207,6 +209,8 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
        });
        pref.setOnPreferenceChangeListener((preference, newValue) -> false);
        pref.setSingleLineTitle(true);
        pref.checkEcmRestrictionAndSetDisabled(Manifest.permission.BIND_DEVICE_ADMIN,
                item.getPackageName(), item.getUid());
    }

    /**