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

Commit 15b701b0 authored by Neil Fuller's avatar Neil Fuller
Browse files

Add internal service paths for enterprise setup

Add internal service paths for enterprise device initialization through
the addition of several TimeDetectorInternal and
TimeZoneDetectorInternal methods that are intended for use by
DevicePolicyManagerService (in a later commit).

Many of the changes to service code relate to the need to bypass user
policy checks for the new usecases (which don't need to enforce them,
because they are acting on behalf of a "device admin").

A check to enforce user policy checks for setting time has been added as
part of this commit. The absence looks like an omission.

This commit changes some permission checks in *Service classes to be
more restrictive, i.e. enforceCallingOrSelfPermission() ->
enforceCallingPermission().  Looking at the history the "OrSelf" was
originally added for enterprise use cases (since calls were made via
*Service), and some were just copy-and-pastes.  With dedicated paths
being added for enterprise via *Internal APIs, the "OrSelf" shouldn't be
needed as there are no binder calls involved for enterprise.

This commit switches some test code to using Mockito's spy() for
call-tracking to simplify hand-rolled fakes. It also adds a new
dependency on the junit-params for easier parameterization of test
methods.

Bug: 236612872
Test: atest services/tests/servicestests/src/com/android/server/timedetector/
Test: atest services/tests/servicestests/src/com/android/server/timezonedetector/
Change-Id: Ie5a8cccbb092077c000abd24854b70917d5e324d
parent c502fe48
Loading
Loading
Loading
Loading
+23 −11
Original line number Diff line number Diff line
@@ -155,21 +155,33 @@ public final class ConfigurationInternal {
        return UserHandle.of(mUserId);
    }

    /** Returns true if the user allowed to modify time zone configuration. */
    /**
     * Returns true if the user is allowed to modify time configuration, e.g. can be false due
     * to device policy (enterprise).
     *
     * <p>See also {@link #createCapabilitiesAndConfig(boolean)} for situations where this
     * value are ignored.
     */
    public boolean isUserConfigAllowed() {
        return mUserConfigAllowed;
    }

    /** Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values. */
    public TimeCapabilitiesAndConfig capabilitiesAndConfig() {
        return new TimeCapabilitiesAndConfig(timeCapabilities(), timeConfiguration());
    /**
     * Returns a {@link TimeCapabilitiesAndConfig} objects based on configuration values.
     *
     * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
     *   policy restrictions that should apply to actual users can be ignored
     */
    public TimeCapabilitiesAndConfig createCapabilitiesAndConfig(boolean bypassUserPolicyChecks) {
        return new TimeCapabilitiesAndConfig(
                timeCapabilities(bypassUserPolicyChecks), timeConfiguration());
    }

    private TimeCapabilities timeCapabilities() {
    private TimeCapabilities timeCapabilities(boolean bypassUserPolicyChecks) {
        UserHandle userHandle = UserHandle.of(mUserId);
        TimeCapabilities.Builder builder = new TimeCapabilities.Builder(userHandle);

        boolean allowConfigDateTime = isUserConfigAllowed();
        boolean allowConfigDateTime = isUserConfigAllowed() || bypassUserPolicyChecks;

        boolean deviceHasAutoTimeDetection = isAutoDetectionSupported();
        final @CapabilityState int configureAutoDetectionEnabledCapability;
@@ -186,15 +198,15 @@ public final class ConfigurationInternal {
        // current logic above, this could lead to a situation where a device hardware does not
        // support auto detection, the device has been forced into "auto" mode by an admin and the
        // user is unable to disable auto detection.
        final @CapabilityState int suggestManualTimeZoneCapability;
        final @CapabilityState int suggestManualTimeCapability;
        if (!allowConfigDateTime) {
            suggestManualTimeZoneCapability = CAPABILITY_NOT_ALLOWED;
            suggestManualTimeCapability = CAPABILITY_NOT_ALLOWED;
        } else if (getAutoDetectionEnabledBehavior()) {
            suggestManualTimeZoneCapability = CAPABILITY_NOT_APPLICABLE;
            suggestManualTimeCapability = CAPABILITY_NOT_APPLICABLE;
        } else {
            suggestManualTimeZoneCapability = CAPABILITY_POSSESSED;
            suggestManualTimeCapability = CAPABILITY_POSSESSED;
        }
        builder.setSetManualTimeCapability(suggestManualTimeZoneCapability);
        builder.setSetManualTimeCapability(suggestManualTimeCapability);

        return builder.build();
    }
+7 −3
Original line number Diff line number Diff line
@@ -53,11 +53,15 @@ public interface ServiceConfigAccessor {
    /**
     * Updates the configuration properties that control a device's time behavior.
     *
     * <p>This method returns {@code true} if the configuration was changed,
     * {@code false} otherwise.
     * <p>This method returns {@code true} if the configuration was changed, {@code false}
     * otherwise.
     *
     * @param bypassUserPolicyChecks {@code true} for device policy manager use cases where device
     *   policy restrictions that should apply to actual users can be ignored
     */
    boolean updateConfiguration(
            @UserIdInt int userId, @NonNull TimeConfiguration requestedConfiguration);
            @UserIdInt int userId, @NonNull TimeConfiguration requestedConfiguration,
            boolean bypassUserPolicyChecks);

    /**
     * Returns a snapshot of the configuration that controls time zone detector behavior for the
+3 −3
Original line number Diff line number Diff line
@@ -194,11 +194,11 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {

    @Override
    public synchronized boolean updateConfiguration(@UserIdInt int userId,
            @NonNull TimeConfiguration requestedConfiguration) {
            @NonNull TimeConfiguration requestedConfiguration, boolean bypassUserPolicyChecks) {
        Objects.requireNonNull(requestedConfiguration);

        TimeCapabilitiesAndConfig capabilitiesAndConfig =
                getCurrentUserConfigurationInternal().capabilitiesAndConfig();
        TimeCapabilitiesAndConfig capabilitiesAndConfig = getCurrentUserConfigurationInternal()
                .createCapabilitiesAndConfig(bypassUserPolicyChecks);
        TimeCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
        TimeConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();

+33 −2
Original line number Diff line number Diff line
@@ -17,16 +17,47 @@
package com.android.server.timedetector;

import android.annotation.NonNull;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
import android.app.timedetector.ManualTimeSuggestion;

/**
 * The internal (in-process) system server API for the {@link
 * com.android.server.timedetector.TimeDetectorService}.
 * The internal (in-process) system server API for the time detector service.
 *
 * <p>The methods on this class can be called from any thread.
 *
 * <p>Methods marked with "[For device policy manager only]" are for use by the device policy
 * manager to set device state and must not enforce device policy restrictions.
 *
 * @hide
 */
public interface TimeDetectorInternal {

    /**
     * [For device policy manager only] Returns a snapshot of the configuration that controls time
     * detector behavior for the current user.
     */
    @NonNull
    TimeCapabilitiesAndConfig getCapabilitiesAndConfigForDpm();

    /**
     * [For device policy manager only] Updates the configuration properties that control a device's
     * time behavior for the current user.
     *
     * <p>This method returns {@code true} if the configuration was changed, {@code false}
     * otherwise.
     */
    boolean updateConfigurationForDpm(@NonNull TimeConfiguration configuration);

    /**
     * [For device policy manager only] Attempts to set the device to a manually entered time.
     * Returns {@code false} if the suggestion is invalid, or the device configuration prevents the
     * suggestion being used, {@code true} if the suggestion has been accepted. A suggestion that is
     * valid but does not change the time because it matches the current device time is considered
     * accepted.
     */
    boolean setManualTimeForDpm(@NonNull ManualTimeSuggestion manualTimeSuggestion);

    /** Used to pass new network time suggestions to the time detector. */
    void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal);

+39 −0
Original line number Diff line number Diff line
@@ -17,9 +17,14 @@
package com.android.server.timedetector;

import android.annotation.NonNull;
import android.app.time.TimeCapabilitiesAndConfig;
import android.app.time.TimeConfiguration;
import android.app.timedetector.ManualTimeSuggestion;
import android.content.Context;
import android.os.Handler;

import com.android.server.timezonedetector.CurrentUserIdentityInjector;

import java.util.Objects;

/**
@@ -31,15 +36,49 @@ public class TimeDetectorInternalImpl implements TimeDetectorInternal {

    @NonNull private final Context mContext;
    @NonNull private final Handler mHandler;
    @NonNull private final CurrentUserIdentityInjector mCurrentUserIdentityInjector;
    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
    @NonNull private final TimeDetectorStrategy mTimeDetectorStrategy;

    public TimeDetectorInternalImpl(@NonNull Context context, @NonNull Handler handler,
            @NonNull CurrentUserIdentityInjector currentUserIdentityInjector,
            @NonNull ServiceConfigAccessor serviceConfigAccessor,
            @NonNull TimeDetectorStrategy timeDetectorStrategy) {
        mContext = Objects.requireNonNull(context);
        mHandler = Objects.requireNonNull(handler);
        mCurrentUserIdentityInjector = Objects.requireNonNull(currentUserIdentityInjector);
        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
        mTimeDetectorStrategy = Objects.requireNonNull(timeDetectorStrategy);
    }

    @Override
    @NonNull
    public TimeCapabilitiesAndConfig getCapabilitiesAndConfigForDpm() {
        int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
        final boolean bypassUserPolicyCheck = true;
        ConfigurationInternal configurationInternal =
                mServiceConfigAccessor.getConfigurationInternal(currentUserId);
        return configurationInternal.createCapabilitiesAndConfig(bypassUserPolicyCheck);
    }

    @Override
    public boolean updateConfigurationForDpm(@NonNull TimeConfiguration configuration) {
        Objects.requireNonNull(configuration);

        int currentUserId = mCurrentUserIdentityInjector.getCurrentUserId();
        final boolean bypassUserPolicyCheck = true;
        return mServiceConfigAccessor.updateConfiguration(
                currentUserId, configuration, bypassUserPolicyCheck);
    }

    @Override
    public boolean setManualTimeForDpm(@NonNull ManualTimeSuggestion timeSignal) {
        Objects.requireNonNull(timeSignal);

        int userId = mCurrentUserIdentityInjector.getCurrentUserId();
        return mTimeDetectorStrategy.suggestManualTime(userId, timeSignal, false);
    }

    @Override
    public void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSignal) {
        Objects.requireNonNull(timeSignal);
Loading