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

Commit f84c6ee0 authored by Zoltan Szatmary-Ban's avatar Zoltan Szatmary-Ban Committed by Android (Google) Code Review
Browse files

Merge "Make Location Settings multiprofile aware" into lmp-mr1-dev

parents 07117147 86c877e9
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -26,6 +26,21 @@
            settings:keywords="@string/keywords_location_mode"
            android:summary="@string/location_mode_location_off_title" />

        <!-- This preference category gets removed if there is no managed profile -->
        <PreferenceCategory
            android:key="managed_profile_location_category"
            android:title="@string/managed_profile_location_category">

            <Preference
                android:key="managed_profile_location_switch"
                android:title="@string/managed_profile_location_switch_title"
                android:summary="@string/managed_profile_location_switch_lockdown"
                android:persistent="false"
                android:enabled="false"
                android:selectable="false" />

        </PreferenceCategory>

        <PreferenceCategory
            android:key="recent_location_requests"
            android:title="@string/location_category_recent_location_requests" />
+23 −3
Original line number Diff line number Diff line
@@ -16,10 +16,14 @@

package com.android.settings.location;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

/**
 * A preference item that can dim the icon when it's disabled, either directly or because its parent
@@ -29,16 +33,23 @@ public class DimmableIconPreference extends Preference {
    private static final int ICON_ALPHA_ENABLED = 255;
    private static final int ICON_ALPHA_DISABLED = 102;

    public DimmableIconPreference(Context context, AttributeSet attrs, int defStyle) {
    private final CharSequence mContentDescription;

    public DimmableIconPreference(Context context, AttributeSet attrs, int defStyle,
            @Nullable CharSequence contentDescription) {
        super(context, attrs, defStyle);
        mContentDescription = contentDescription;
    }

    public DimmableIconPreference(Context context, AttributeSet attrs) {
    public DimmableIconPreference(Context context, AttributeSet attrs,
            @Nullable CharSequence contentDescription) {
        super(context, attrs);
        mContentDescription = contentDescription;
    }

    public DimmableIconPreference(Context context) {
    public DimmableIconPreference(Context context, @Nullable CharSequence contentDescription) {
        super(context);
        mContentDescription = contentDescription;
    }

    private void dimIcon(boolean dimmed) {
@@ -60,4 +71,13 @@ public class DimmableIconPreference extends Preference {
        dimIcon(!enabled);
        super.setEnabled(enabled);
    }

    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
        if (!TextUtils.isEmpty(mContentDescription)) {
            final TextView titleView = (TextView) view.findViewById(android.R.id.title);
            titleView.setContentDescription(mContentDescription);
        }
    }
}
+14 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.settings.location;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.os.UserHandle;
import com.android.internal.annotations.Immutable;
import com.android.internal.util.Preconditions;

@@ -52,6 +53,11 @@ class InjectedSetting {
     */
    public final int iconId;

    /**
     * The user/profile associated with this setting (e.g. managed profile)
     */
    public final UserHandle mUserHandle;

    /**
     * The activity to launch to allow the user to modify the settings value. Assumed to be in the
     * {@link #packageName} package.
@@ -59,11 +65,12 @@ class InjectedSetting {
    public final String settingsActivity;

    private InjectedSetting(String packageName, String className,
            String title, int iconId, String settingsActivity) {
            String title, int iconId, UserHandle userHandle, String settingsActivity) {
        this.packageName = Preconditions.checkNotNull(packageName, "packageName");
        this.className = Preconditions.checkNotNull(className, "className");
        this.title = Preconditions.checkNotNull(title, "title");
        this.iconId = iconId;
        this.mUserHandle = userHandle;
        this.settingsActivity = Preconditions.checkNotNull(settingsActivity);
    }

@@ -71,7 +78,7 @@ class InjectedSetting {
     * Returns a new instance, or null.
     */
    public static InjectedSetting newInstance(String packageName, String className,
            String title, int iconId, String settingsActivity) {
            String title, int iconId, UserHandle userHandle, String settingsActivity) {
        if (packageName == null || className == null ||
                TextUtils.isEmpty(title) || TextUtils.isEmpty(settingsActivity)) {
            if (Log.isLoggable(SettingsInjector.TAG, Log.WARN)) {
@@ -81,7 +88,8 @@ class InjectedSetting {
            }
            return null;
        }
        return new InjectedSetting(packageName, className, title, iconId, settingsActivity);
        return new InjectedSetting(packageName, className, title, iconId, userHandle,
                settingsActivity);
    }

    @Override
@@ -91,6 +99,7 @@ class InjectedSetting {
                ", mClassName='" + className + '\'' +
                ", label=" + title +
                ", iconId=" + iconId +
                ", userId=" + mUserHandle.getIdentifier() +
                ", settingsActivity='" + settingsActivity + '\'' +
                '}';
    }
@@ -113,6 +122,7 @@ class InjectedSetting {

        return packageName.equals(that.packageName) && className.equals(that.className)
                && title.equals(that.title) && iconId == that.iconId
                && mUserHandle.equals(that.mUserHandle)
                && settingsActivity.equals(that.settingsActivity);
    }

@@ -122,6 +132,7 @@ class InjectedSetting {
        result = 31 * result + className.hashCode();
        result = 31 * result + title.hashCode();
        result = 31 * result + iconId;
        result = 31 * result + mUserHandle.hashCode();
        result = 31 * result + settingsActivity.hashCode();
        return result;
    }
+74 −4
Original line number Diff line number Diff line
@@ -21,16 +21,22 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.SettingInjectorService;
import android.os.Binder;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.util.Log;
import android.widget.Switch;

import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.widget.SwitchBar;

import java.util.Collections;
@@ -45,6 +51,17 @@ public class LocationSettings extends LocationSettingsBase

    private static final String TAG = "LocationSettings";

    /**
     * Key for managed profile location preference category. Category is shown only
     * if there is a managed profile
     */
    private static final String KEY_MANAGED_PROFILE_CATEGORY = "managed_profile_location_category";
    /**
     * Key for managed profile location preference. Note it used to be a switch pref and we had to
     * keep the key as strings had been submitted for string freeze before the decision to
     * demote this to a simple preference was made. TODO: Candidate for refactoring.
     */
    private static final String KEY_MANAGED_PROFILE_PREFERENCE = "managed_profile_location_switch";
    /** Key for preference screen "Mode" */
    private static final String KEY_LOCATION_MODE = "location_mode";
    /** Key for preference category "Recent location requests" */
@@ -55,17 +72,21 @@ public class LocationSettings extends LocationSettingsBase
    private SwitchBar mSwitchBar;
    private Switch mSwitch;
    private boolean mValidListener = false;
    private UserHandle mManagedProfile;
    private Preference mManagedProfilePreference;
    private Preference mLocationMode;
    private PreferenceCategory mCategoryRecentLocationRequests;
    /** Receives UPDATE_INTENT  */
    private BroadcastReceiver mReceiver;
    private SettingsInjector injector;
    private UserManager mUm;

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

        final SettingsActivity activity = (SettingsActivity) getActivity();
        mUm = (UserManager) activity.getSystemService(Context.USER_SERVICE);

        mSwitchBar = activity.getSwitchBar();
        mSwitch = mSwitchBar.getSwitch();
@@ -127,6 +148,7 @@ public class LocationSettings extends LocationSettingsBase
        addPreferencesFromResource(R.xml.location_settings);
        root = getPreferenceScreen();

        setupManagedProfileCategory(root);
        mLocationMode = root.findPreference(KEY_LOCATION_MODE);
        mLocationMode.setOnPreferenceClickListener(
                new Preference.OnPreferenceClickListener() {
@@ -155,12 +177,42 @@ public class LocationSettings extends LocationSettingsBase
            mCategoryRecentLocationRequests.addPreference(banner);
        }

        addLocationServices(activity, root);
        boolean lockdownOnLocationAccess = false;
        // Checking if device policy has put a location access lock-down on the managed
        // profile. If managed profile has lock-down on location access then its
        // injected location services must not be shown.
        if (mManagedProfile != null
                && mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)) {
            lockdownOnLocationAccess = true;
        }
        addLocationServices(activity, root, lockdownOnLocationAccess);

        refreshLocationMode();
        return root;
    }

    private void setupManagedProfileCategory(PreferenceScreen root) {
        // Looking for a managed profile. If there are no managed profiles then we are removing the
        // managed profile category.
        mManagedProfile = Utils.getManagedProfile(mUm);
        if (mManagedProfile == null) {
            // There is no managed profile
            root.removePreference(root.findPreference(KEY_MANAGED_PROFILE_CATEGORY));
            mManagedProfilePreference = null;
        } else {
            mManagedProfilePreference = root.findPreference(KEY_MANAGED_PROFILE_PREFERENCE);
            mManagedProfilePreference.setOnPreferenceClickListener(null);
        }
    }

    private void changeManagedProfileLocationAccessStatus(boolean enabled, int summaryResId) {
        if (mManagedProfilePreference == null) {
            return;
        }
        mManagedProfilePreference.setEnabled(enabled);
        mManagedProfilePreference.setSummary(summaryResId);
    }

    /**
     * Add the settings injected by external apps into the "App Settings" category. Hides the
     * category if there are no injected settings.
@@ -168,11 +220,15 @@ public class LocationSettings extends LocationSettingsBase
     * Reloads the settings whenever receives
     * {@link SettingInjectorService#ACTION_INJECTED_SETTING_CHANGED}.
     */
    private void addLocationServices(Context context, PreferenceScreen root) {
    private void addLocationServices(Context context, PreferenceScreen root,
            boolean lockdownOnLocationAccess) {
        PreferenceCategory categoryLocationServices =
                (PreferenceCategory) root.findPreference(KEY_LOCATION_SERVICES);
        injector = new SettingsInjector(context);
        List<Preference> locationServices = injector.getInjectedSettings();
        // If location access is locked down by device policy then we only show injected settings
        // for the primary profile.
        List<Preference> locationServices = injector.getInjectedSettings(lockdownOnLocationAccess ?
                UserHandle.myUserId() : UserHandle.USER_CURRENT);

        mReceiver = new BroadcastReceiver() {
            @Override
@@ -223,7 +279,7 @@ public class LocationSettings extends LocationSettingsBase
        // Restricted user can't change the location mode, so disable the master switch. But in some
        // corner cases, the location might still be enabled. In such case the master switch should
        // be disabled but checked.
        boolean enabled = (mode != android.provider.Settings.Secure.LOCATION_MODE_OFF);
        final boolean enabled = (mode != android.provider.Settings.Secure.LOCATION_MODE_OFF);
        // Disable the whole switch bar instead of the switch itself. If we disabled the switch
        // only, it would be re-enabled again if the switch bar is not disabled.
        mSwitchBar.setEnabled(!restricted);
@@ -240,6 +296,20 @@ public class LocationSettings extends LocationSettingsBase
                mSwitchBar.addOnSwitchChangeListener(this);
            }
        }

        if (mManagedProfilePreference != null) {
            if (mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)) {
                changeManagedProfileLocationAccessStatus(false,
                        R.string.managed_profile_location_switch_lockdown);
            } else {
                if (enabled) {
                    changeManagedProfileLocationAccessStatus(true, R.string.switch_on_text);
                } else {
                    changeManagedProfileLocationAccessStatus(false, R.string.switch_off_text);
                }
            }
        }

        // As a safety measure, also reloads on location mode change to ensure the settings are
        // up-to-date even if an affected app doesn't send the setting changed broadcast.
        injector.reloadStatusMessages();
+8 −25
Original line number Diff line number Diff line
@@ -77,35 +77,13 @@ public class RecentLocationApps {
        }
    }

    /**
     * Subclass of {@link Preference} to intercept views and allow content description to be set on
     * them for accessibility purposes.
     */
    private static class AccessiblePreference extends DimmableIconPreference {
        public CharSequence mContentDescription;

        public AccessiblePreference(Context context, CharSequence contentDescription) {
            super(context);
            mContentDescription = contentDescription;
        }

        @Override
        protected void onBindView(View view) {
            super.onBindView(view);
            if (mContentDescription != null) {
                final TextView titleView = (TextView) view.findViewById(android.R.id.title);
                titleView.setContentDescription(mContentDescription);
            }
        }
    }

    private AccessiblePreference createRecentLocationEntry(
    private DimmableIconPreference createRecentLocationEntry(
            Drawable icon,
            CharSequence label,
            boolean isHighBattery,
            CharSequence contentDescription,
            Preference.OnPreferenceClickListener listener) {
        AccessiblePreference pref = new AccessiblePreference(mActivity, contentDescription);
        DimmableIconPreference pref = new DimmableIconPreference(mActivity, contentDescription);
        pref.setIcon(icon);
        pref.setTitle(label);
        if (isHighBattery) {
@@ -198,7 +176,7 @@ public class RecentLocationApps {
        int uid = ops.getUid();
        int userId = UserHandle.getUserId(uid);

        AccessiblePreference preference = null;
        DimmableIconPreference preference = null;
        try {
            IPackageManager ipm = AppGlobals.getPackageManager();
            ApplicationInfo appInfo =
@@ -215,6 +193,11 @@ public class RecentLocationApps {
            Drawable icon = mPackageManager.getUserBadgedIcon(appIcon, userHandle);
            CharSequence appLabel = mPackageManager.getApplicationLabel(appInfo);
            CharSequence badgedAppLabel = mPackageManager.getUserBadgedLabel(appLabel, userHandle);
            if (appLabel.toString().contentEquals(badgedAppLabel)) {
                // If badged label is not different from original then no need for it as
                // a separate content description.
                badgedAppLabel = null;
            }
            preference = createRecentLocationEntry(icon,
                    appLabel, highBattery, badgedAppLabel,
                    new PackageEntryClickedListener(packageName));
Loading