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

Commit 53239cfc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add shell commands and other support for host CTS"

parents bb45c563 9e34ba7c
Loading
Loading
Loading
Loading
+44 −32
Original line number Original line Diff line number Diff line
@@ -40,17 +40,58 @@ public final class LocationTimeZoneManager {
    public static final String SHELL_COMMAND_SERVICE_NAME = "location_time_zone_manager";
    public static final String SHELL_COMMAND_SERVICE_NAME = "location_time_zone_manager";


    /**
    /**
     * Shell command that starts the service (after stop).
     * A shell command that starts the service (after stop).
     */
     */
    public static final String SHELL_COMMAND_START = "start";
    public static final String SHELL_COMMAND_START = "start";


    /**
    /**
     * Shell command that stops the service.
     * A shell command that stops the service.
     */
     */
    public static final String SHELL_COMMAND_STOP = "stop";
    public static final String SHELL_COMMAND_STOP = "stop";


    /**
    /**
     * Shell command that sends test commands to a provider
     * A shell command that can put providers into different modes. Takes effect next time the
     * service is started.
     */
    public static final String SHELL_COMMAND_SET_PROVIDER_MODE_OVERRIDE =
            "set_provider_mode_override";

    /**
     * The default provider mode.
     * For use with {@link #SHELL_COMMAND_SET_PROVIDER_MODE_OVERRIDE}.
     */
    public static final String PROVIDER_MODE_OVERRIDE_NONE = "none";

    /**
     * The "simulated" provider mode.
     * For use with {@link #SHELL_COMMAND_SET_PROVIDER_MODE_OVERRIDE}.
     */
    public static final String PROVIDER_MODE_OVERRIDE_SIMULATED = "simulated";

    /**
     * The "disabled" provider mode (equivalent to there being no provider configured).
     * For use with {@link #SHELL_COMMAND_SET_PROVIDER_MODE_OVERRIDE}.
     */
    public static final String PROVIDER_MODE_OVERRIDE_DISABLED = "disabled";

    /**
     * A shell command that tells the service to record state information during tests. The next
     * argument value is "true" or "false".
     */
    public static final String SHELL_COMMAND_RECORD_PROVIDER_STATES = "record_provider_states";

    /**
     * A shell command that tells the service to dump its current state.
     */
    public static final String SHELL_COMMAND_DUMP_STATE = "dump_state";

    /**
     * Option for {@link #SHELL_COMMAND_DUMP_STATE} that tells it to dump state as a binary proto.
     */
    public static final String DUMP_STATE_OPTION_PROTO = "--proto";

    /**
     * A shell command that sends test commands to a provider
     */
     */
    public static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND =
    public static final String SHELL_COMMAND_SEND_PROVIDER_TEST_COMMAND =
            "send_provider_test_command";
            "send_provider_test_command";
@@ -88,35 +129,6 @@ public final class LocationTimeZoneManager {
     */
     */
    public static final String SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN = "uncertain";
    public static final String SIMULATED_PROVIDER_TEST_COMMAND_UNCERTAIN = "uncertain";


    private static final String SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PREFIX =
            "persist.sys.geotz.";

    /**
     * The name of the system property that can be used to set the primary provider into test mode
     * (value = {@link #SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_SIMULATED}) or disabled (value = {@link
     * #SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_DISABLED}).
     */
    public static final String SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PRIMARY =
            SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PREFIX + PRIMARY_PROVIDER_NAME;

    /**
     * The name of the system property that can be used to set the secondary provider into test mode
     * (value = {@link #SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_SIMULATED}) or disabled (value = {@link
     * #SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_DISABLED}).
     */
    public static final String SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_SECONDARY =
            SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PREFIX + SECONDARY_PROVIDER_NAME;

    /**
     * The value of the provider mode system property to put a provider into test mode.
     */
    public static final String SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_SIMULATED = "simulated";

    /**
     * The value of the provider mode system property to put a provider into disabled mode.
     */
    public static final String SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_DISABLED = "disabled";

    private LocationTimeZoneManager() {
    private LocationTimeZoneManager() {
        // No need to instantiate.
        // No need to instantiate.
    }
    }
+61 −3
Original line number Original line Diff line number Diff line
@@ -29,11 +29,69 @@ import android.content.Context;
@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
@SystemService(Context.TIME_ZONE_DETECTOR_SERVICE)
public interface TimeZoneDetector {
public interface TimeZoneDetector {


    /** @hide */
    /**
     * The name of the service for shell commands.
     * @hide
     */
    String SHELL_COMMAND_SERVICE_NAME = "time_zone_detector";

    /**
     * A shell command that prints the current "auto time zone detection" global setting value.
     * @hide
     */
    String SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED = "is_auto_detection_enabled";

    /**
     * A shell command that sets the current "auto time zone detection" global setting value.
     * @hide
     */
    String SHELL_COMMAND_SET_AUTO_DETECTION_ENABLED = "set_auto_detection_enabled";

    /**
     * A shell command that prints whether the geolocation-based time zone detection feature is
     * supported on the device.
     * @hide
     */
    String SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED = "is_geo_detection_supported";

    /**
     * A shell command that prints the current user's "location enabled" setting.
     * @hide
     */
    String SHELL_COMMAND_IS_LOCATION_ENABLED = "is_location_enabled";

    /**
     * A shell command that prints the current user's "location-based time zone detection enabled"
     * setting.
     * @hide
     */
    String SHELL_COMMAND_IS_GEO_DETECTION_ENABLED = "is_geo_detection_enabled";

    /**
     * A shell command that sets the current user's "location-based time zone detection enabled"
     * setting.
     * @hide
     */
    String SHELL_COMMAND_SET_GEO_DETECTION_ENABLED = "set_geo_detection_enabled";

    /**
     * A shell command that injects a geolocation time zone suggestion (as if from the
     * location_time_zone_manager).
     * @hide
     */
    String SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE = "suggest_geo_location_time_zone";
    String SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE = "suggest_geo_location_time_zone";
    /** @hide */

    /**
     * A shell command that injects a manual time zone suggestion (as if from the SettingsUI or
     * similar).
     * @hide
     */
    String SHELL_COMMAND_SUGGEST_MANUAL_TIME_ZONE = "suggest_manual_time_zone";
    String SHELL_COMMAND_SUGGEST_MANUAL_TIME_ZONE = "suggest_manual_time_zone";
    /** @hide */

    /**
     * A shell command that injects a telephony time zone suggestion (as if from the phone app).
     * @hide
     */
    String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE = "suggest_telephony_time_zone";
    String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE = "suggest_telephony_time_zone";


    /**
    /**
+32 −0
Original line number Original line Diff line number Diff line
@@ -610,6 +610,38 @@ class ControllerImpl extends LocationTimeZoneProviderController {
        }
        }
    }
    }


    /**
     * Sets whether the controller should record provider state changes for later dumping via
     * {@link #getStateForTests()}.
     */
    void setProviderStateRecordingEnabled(boolean enabled) {
        mThreadingDomain.assertCurrentThread();

        synchronized (mSharedLock) {
            mPrimaryProvider.setStateChangeRecordingEnabled(enabled);
            mSecondaryProvider.setStateChangeRecordingEnabled(enabled);
        }
    }

    /**
     * Returns a snapshot of the current controller state for tests.
     */
    @NonNull
    LocationTimeZoneManagerServiceState getStateForTests() {
        mThreadingDomain.assertCurrentThread();

        synchronized (mSharedLock) {
            LocationTimeZoneManagerServiceState.Builder builder =
                    new LocationTimeZoneManagerServiceState.Builder();
            if (mLastSuggestion != null) {
                builder.setLastSuggestion(mLastSuggestion);
            }
            builder.setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
                    .setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
            return builder.build();
        }
    }

    @Nullable
    @Nullable
    private LocationTimeZoneProvider getLocationTimeZoneProvider(@NonNull String providerName) {
    private LocationTimeZoneProvider getLocationTimeZoneProvider(@NonNull String providerName) {
        LocationTimeZoneProvider targetProvider;
        LocationTimeZoneProvider targetProvider;
+84 −25
Original line number Original line Diff line number Diff line
@@ -17,11 +17,10 @@
package com.android.server.location.timezone;
package com.android.server.location.timezone;


import static android.app.time.LocationTimeZoneManager.PRIMARY_PROVIDER_NAME;
import static android.app.time.LocationTimeZoneManager.PRIMARY_PROVIDER_NAME;
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_DISABLED;
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_NONE;
import static android.app.time.LocationTimeZoneManager.PROVIDER_MODE_OVERRIDE_SIMULATED;
import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
import static android.app.time.LocationTimeZoneManager.SECONDARY_PROVIDER_NAME;
import static android.app.time.LocationTimeZoneManager.SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PRIMARY;
import static android.app.time.LocationTimeZoneManager.SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_SECONDARY;
import static android.app.time.LocationTimeZoneManager.SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_DISABLED;
import static android.app.time.LocationTimeZoneManager.SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_SIMULATED;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -33,7 +32,6 @@ import android.os.Handler;
import android.os.RemoteCallback;
import android.os.RemoteCallback;
import android.os.ResultReceiver;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.ShellCallback;
import android.os.SystemProperties;
import android.service.timezone.TimeZoneProviderService;
import android.service.timezone.TimeZoneProviderService;
import android.util.IndentingPrintWriter;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Log;
@@ -42,6 +40,7 @@ import android.util.Slog;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.FgThread;
import com.android.server.SystemService;
import com.android.server.SystemService;
import com.android.server.timezonedetector.TimeZoneDetectorInternal;
import com.android.server.timezonedetector.TimeZoneDetectorInternal;
@@ -161,6 +160,14 @@ public class LocationTimeZoneManagerService extends Binder {
    @GuardedBy("mSharedLock")
    @GuardedBy("mSharedLock")
    private ControllerEnvironmentImpl mEnvironment;
    private ControllerEnvironmentImpl mEnvironment;


    @GuardedBy("mSharedLock")
    @NonNull
    private String mPrimaryProviderModeOverride = PROVIDER_MODE_OVERRIDE_NONE;

    @GuardedBy("mSharedLock")
    @NonNull
    private String mSecondaryProviderModeOverride = PROVIDER_MODE_OVERRIDE_NONE;

    LocationTimeZoneManagerService(Context context) {
    LocationTimeZoneManagerService(Context context) {
        mContext = context.createAttributionContext(ATTRIBUTION_TAG);
        mContext = context.createAttributionContext(ATTRIBUTION_TAG);
        mHandler = FgThread.getHandler();
        mHandler = FgThread.getHandler();
@@ -231,9 +238,9 @@ public class LocationTimeZoneManagerService extends Binder {


    private LocationTimeZoneProvider createPrimaryProvider() {
    private LocationTimeZoneProvider createPrimaryProvider() {
        LocationTimeZoneProviderProxy proxy;
        LocationTimeZoneProviderProxy proxy;
        if (isInSimulationMode(PRIMARY_PROVIDER_NAME)) {
        if (isProviderInSimulationMode(PRIMARY_PROVIDER_NAME)) {
            proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
            proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
        } else if (isDisabled(PRIMARY_PROVIDER_NAME)) {
        } else if (isProviderDisabled(PRIMARY_PROVIDER_NAME)) {
            proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
            proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
        } else {
        } else {
            proxy = new RealLocationTimeZoneProviderProxy(
            proxy = new RealLocationTimeZoneProviderProxy(
@@ -250,9 +257,9 @@ public class LocationTimeZoneManagerService extends Binder {


    private LocationTimeZoneProvider createSecondaryProvider() {
    private LocationTimeZoneProvider createSecondaryProvider() {
        LocationTimeZoneProviderProxy proxy;
        LocationTimeZoneProviderProxy proxy;
        if (isInSimulationMode(SECONDARY_PROVIDER_NAME)) {
        if (isProviderInSimulationMode(SECONDARY_PROVIDER_NAME)) {
            proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
            proxy = new SimulatedLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
        } else if (isDisabled(SECONDARY_PROVIDER_NAME)) {
        } else if (isProviderDisabled(SECONDARY_PROVIDER_NAME)) {
            proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
            proxy = new NullLocationTimeZoneProviderProxy(mContext, mThreadingDomain);
        } else {
        } else {
            proxy = new RealLocationTimeZoneProviderProxy(
            proxy = new RealLocationTimeZoneProviderProxy(
@@ -268,16 +275,14 @@ public class LocationTimeZoneManagerService extends Binder {
    }
    }


    /** Used for bug triage and in tests to simulate provider events. */
    /** Used for bug triage and in tests to simulate provider events. */
    private static boolean isInSimulationMode(String providerName) {
    private boolean isProviderInSimulationMode(String providerName) {
        return isProviderModeSetInSystemProperties(providerName,
        return isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_SIMULATED);
                SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_SIMULATED);
    }
    }


    /** Used for bug triage, tests and experiments to remove a provider. */
    /** Used for bug triage, tests and experiments to remove a provider. */
    private boolean isDisabled(String providerName) {
    private boolean isProviderDisabled(String providerName) {
        return !isProviderEnabledInConfig(providerName)
        return !isProviderEnabledInConfig(providerName)
                || isProviderModeSetInSystemProperties(
                || isProviderModeOverrideSet(providerName, PROVIDER_MODE_OVERRIDE_DISABLED);
                        providerName, SYSTEM_PROPERTY_VALUE_PROVIDER_MODE_DISABLED);
    }
    }


    private boolean isProviderEnabledInConfig(String providerName) {
    private boolean isProviderEnabledInConfig(String providerName) {
@@ -299,25 +304,18 @@ public class LocationTimeZoneManagerService extends Binder {
        return resources.getBoolean(providerEnabledConfigId);
        return resources.getBoolean(providerEnabledConfigId);
    }
    }


    private static boolean isProviderModeSetInSystemProperties(
    private boolean isProviderModeOverrideSet(@NonNull String providerName, @NonNull String mode) {
            @NonNull String providerName, @NonNull String mode) {
        String systemPropertyKey;
        switch (providerName) {
        switch (providerName) {
            case PRIMARY_PROVIDER_NAME: {
            case PRIMARY_PROVIDER_NAME: {
                systemPropertyKey = SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_PRIMARY;
                return Objects.equals(mPrimaryProviderModeOverride, mode);
                break;
            }
            }
            case SECONDARY_PROVIDER_NAME: {
            case SECONDARY_PROVIDER_NAME: {
                systemPropertyKey = SYSTEM_PROPERTY_KEY_PROVIDER_MODE_OVERRIDE_SECONDARY;
                return Objects.equals(mSecondaryProviderModeOverride, mode);
                break;
            }
            }
            default: {
            default: {
                throw new IllegalArgumentException(providerName);
                throw new IllegalArgumentException(providerName);
            }
            }
        }
        }

        String systemPropertyProviderMode = SystemProperties.get(systemPropertyKey, null);
        return Objects.equals(systemPropertyProviderMode, mode);
    }
    }


    /**
    /**
@@ -347,6 +345,67 @@ public class LocationTimeZoneManagerService extends Binder {
                this, in, out, err, args, callback, resultReceiver);
                this, in, out, err, args, callback, resultReceiver);
    }
    }


    /** Sets this service into provider state recording mode for tests. */
    void setProviderModeOverride(@NonNull String providerName, @NonNull String mode) {
        enforceManageTimeZoneDetectorPermission();

        Preconditions.checkArgument(
                PRIMARY_PROVIDER_NAME.equals(providerName)
                        || SECONDARY_PROVIDER_NAME.equals(providerName));
        Preconditions.checkArgument(PROVIDER_MODE_OVERRIDE_DISABLED.equals(mode)
                || PROVIDER_MODE_OVERRIDE_SIMULATED.equals(mode)
                || PROVIDER_MODE_OVERRIDE_NONE.equals(mode));

        mThreadingDomain.postAndWait(() -> {
            synchronized (mSharedLock) {
                switch (providerName) {
                    case PRIMARY_PROVIDER_NAME: {
                        mPrimaryProviderModeOverride = mode;
                        break;
                    }
                    case SECONDARY_PROVIDER_NAME: {
                        mSecondaryProviderModeOverride = mode;
                        break;
                    }
                }
            }
        }, BLOCKING_OP_WAIT_DURATION_MILLIS);
    }

    /** Sets this service into provider state recording mode for tests. */
    void setProviderStateRecordingEnabled(boolean enabled) {
        enforceManageTimeZoneDetectorPermission();

        mThreadingDomain.postAndWait(() -> {
            synchronized (mSharedLock) {
                if (mLocationTimeZoneDetectorController != null) {
                    mLocationTimeZoneDetectorController.setProviderStateRecordingEnabled(enabled);
                }
            }
        }, BLOCKING_OP_WAIT_DURATION_MILLIS);
    }

    /** Returns a snapshot of the current controller state for tests. */
    @NonNull
    LocationTimeZoneManagerServiceState getStateForTests() {
        enforceManageTimeZoneDetectorPermission();

        try {
            return mThreadingDomain.postAndWait(
                    () -> {
                        synchronized (mSharedLock) {
                            if (mLocationTimeZoneDetectorController == null) {
                                return null;
                            }
                            return mLocationTimeZoneDetectorController.getStateForTests();
                        }
                    },
                    BLOCKING_OP_WAIT_DURATION_MILLIS);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
    /**
     * Passes a {@link TestCommand} to the specified provider and waits for the response.
     * Passes a {@link TestCommand} to the specified provider and waits for the response.
     */
     */
+97 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 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.server.location.timezone;

import android.annotation.NonNull;
import android.annotation.Nullable;

import com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/** A snapshot of the location time zone manager service's state for tests. */
final class LocationTimeZoneManagerServiceState {

    @Nullable private final GeolocationTimeZoneSuggestion mLastSuggestion;
    @NonNull private final List<ProviderState> mPrimaryProviderStates;
    @NonNull private final List<ProviderState> mSecondaryProviderStates;

    LocationTimeZoneManagerServiceState(@NonNull Builder builder) {
        mLastSuggestion = builder.mLastSuggestion;
        mPrimaryProviderStates = Objects.requireNonNull(builder.mPrimaryProviderStates);
        mSecondaryProviderStates = Objects.requireNonNull(builder.mSecondaryProviderStates);
    }

    @Nullable
    public GeolocationTimeZoneSuggestion getLastSuggestion() {
        return mLastSuggestion;
    }

    @NonNull
    public List<ProviderState> getPrimaryProviderStates() {
        return Collections.unmodifiableList(mPrimaryProviderStates);
    }

    @NonNull
    public List<ProviderState> getSecondaryProviderStates() {
        return Collections.unmodifiableList(mSecondaryProviderStates);
    }

    @Override
    public String toString() {
        return "LocationTimeZoneManagerServiceState{"
                + "mLastSuggestion=" + mLastSuggestion
                + ", mPrimaryProviderStates=" + mPrimaryProviderStates
                + ", mSecondaryProviderStates=" + mSecondaryProviderStates
                + '}';
    }

    static final class Builder {

        private GeolocationTimeZoneSuggestion mLastSuggestion;
        private List<ProviderState> mPrimaryProviderStates;
        private List<ProviderState> mSecondaryProviderStates;

        @NonNull
        Builder setLastSuggestion(@NonNull GeolocationTimeZoneSuggestion lastSuggestion) {
            mLastSuggestion = Objects.requireNonNull(lastSuggestion);
            return this;
        }

        @NonNull
        Builder setPrimaryProviderStateChanges(@NonNull List<ProviderState> primaryProviderStates) {
            mPrimaryProviderStates = new ArrayList<>(primaryProviderStates);
            return this;
        }

        @NonNull
        Builder setSecondaryProviderStateChanges(
                @NonNull List<ProviderState> secondaryProviderStates) {
            mSecondaryProviderStates = new ArrayList<>(secondaryProviderStates);
            return this;
        }

        @NonNull
        LocationTimeZoneManagerServiceState build() {
            return new LocationTimeZoneManagerServiceState(this);
        }
    }
}
Loading