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

Commit eb370876 authored by Maggie Wang's avatar Maggie Wang Committed by Android (Google) Code Review
Browse files

Merge "Send MODE_CHANGING broadcast before location mode change."

parents 3e4ae1e6 fab2e2cb
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -183,6 +183,17 @@ public class LocationManager {
     */
    public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";

    /**
     * Broadcast intent action when {@link android.provider.Settings.Secure#LOCATION_MODE} is
     * about to be changed through Settings app or Quick Settings.
     * For use with the {@link android.provider.Settings.Secure#LOCATION_MODE} API.
     * If you're interacting with {@link #isProviderEnabled(String)}, use
     * {@link #PROVIDERS_CHANGED_ACTION} instead.
     *
     * @hide
     */
    public static final String MODE_CHANGING_ACTION = "com.android.settings.location.MODE_CHANGING";

    /**
     * Broadcast intent action indicating that the GPS has either started or
     * stopped receiving GPS fixes. An intent extra provides this state as a
+16 −0
Original line number Diff line number Diff line
@@ -14,8 +14,10 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.os.BatteryManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.print.PrintManager;
import android.provider.Settings;
@@ -26,6 +28,10 @@ import com.android.settingslib.drawable.UserIconDrawable;
import java.text.NumberFormat;

public class Utils {

    private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
    private static final String NEW_MODE_KEY = "NEW_MODE";

    private static Signature[] sSystemSignature;
    private static String sPermissionControllerPackageName;
    private static String sServicesSystemSharedLibPackageName;
@@ -39,6 +45,16 @@ public class Utils {
        com.android.internal.R.drawable.ic_wifi_signal_4
    };

    public static boolean updateLocationMode(Context context, int oldMode, int newMode, int userId) {
        Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION);
        intent.putExtra(CURRENT_MODE_KEY, oldMode);
        intent.putExtra(NEW_MODE_KEY, newMode);
        context.sendBroadcastAsUser(
                intent, UserHandle.of(userId), android.Manifest.permission.WRITE_SECURE_SETTINGS);
        return Settings.Secure.putIntForUser(
                context.getContentResolver(), Settings.Secure.LOCATION_MODE, newMode, userId);
    }

    /**
     * Return string resource that best describes combination of tethering
     * options available on this device.
+68 −1
Original line number Diff line number Diff line
@@ -15,20 +15,45 @@
 */
package com.android.settingslib;

import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.text.TextUtils;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatchers;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Resources;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowSettings;

@RunWith(SettingsLibRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@Config(
        manifest = TestConfig.MANIFEST_PATH,
        sdk = TestConfig.SDK_VERSION,
        shadows = {UtilsTest.ShadowSecure.class})
public class UtilsTest {
    private static final double[] TEST_PERCENTAGES = {0, 0.4, 0.5, 0.6, 49, 49.3, 49.8, 50, 100};
    private static final String PERCENTAGE_0 = "0%";
@@ -37,6 +62,29 @@ public class UtilsTest {
    private static final String PERCENTAGE_50 = "50%";
    private static final String PERCENTAGE_100 = "100%";

    private Context mContext;

    @Before
    public void setUp() {
        mContext = spy(RuntimeEnvironment.application);
        ShadowSecure.reset();
    }

    @Test
    public void testUpdateLocationMode_sendBroadcast() {
        int currentUserId = ActivityManager.getCurrentUser();
        Utils.updateLocationMode(
                mContext,
                Secure.LOCATION_MODE_OFF,
                Secure.LOCATION_MODE_HIGH_ACCURACY,
                currentUserId);

        verify(mContext).sendBroadcastAsUser(
                argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
                ArgumentMatchers.eq(UserHandle.of(currentUserId)),
                ArgumentMatchers.eq(WRITE_SECURE_SETTINGS));
    }

    @Test
    public void testFormatPercentage_RoundTrue_RoundUpIfPossible() {
        final String[] expectedPercentages = {PERCENTAGE_0, PERCENTAGE_0, PERCENTAGE_1,
@@ -74,4 +122,23 @@ public class UtilsTest {
                .thenReturn(60);
        assertThat(Utils.getDefaultStorageManagerDaysToRetain(resources)).isEqualTo(60);
    }

    private static ArgumentMatcher<Intent> actionMatches(String expected) {
        return intent -> TextUtils.equals(expected, intent.getAction());
    }

    @Implements(value = Settings.Secure.class)
    public static class ShadowSecure extends ShadowSettings.ShadowSecure {
        private static Map<String, Integer> map = new HashMap<>();

        @Implementation
        public static boolean putIntForUser(ContentResolver cr, String name, int value, int userHandle) {
            map.put(name, value);
            return true;
        }

        public static void reset() {
            map.clear();
        }
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.List;

import static com.android.settingslib.Utils.updateLocationMode;

/**
 * A controller to manage changes of location related states and update the views accordingly.
 */
@@ -106,12 +108,13 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
        final ContentResolver cr = mContext.getContentResolver();
        // When enabling location, a user consent dialog will pop up, and the
        // setting won't be fully enabled until the user accepts the agreement.
        int currentMode = Settings.Secure.getIntForUser(cr, Settings.Secure.LOCATION_MODE, 
                Settings.Secure.LOCATION_MODE_OFF, currentUserId);
        int mode = enabled
                ? Settings.Secure.LOCATION_MODE_PREVIOUS : Settings.Secure.LOCATION_MODE_OFF;
        // QuickSettings always runs as the owner, so specifically set the settings
        // for the current foreground user.
        return Settings.Secure
                .putIntForUser(cr, Settings.Secure.LOCATION_MODE, mode, currentUserId);
        return updateLocationMode(mContext, currentMode, mode, currentUserId);
    }

    /**