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

Commit b3775585 authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

Merge "Moved logic that gets the service name to a separate set of classes."

parents 5b4d008b 0486d20b
Loading
Loading
Loading
Loading
+3 −8
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import com.android.server.autofill.AutofillManagerService.AutofillCompatState;
import com.android.server.autofill.AutofillManagerService.SmartSuggestionMode;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.infra.SecureSettingsServiceNameResolver;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -154,7 +155,8 @@ final class AutofillManagerServiceImpl
    AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory,
            LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui,
            AutofillCompatState autofillCompatState, boolean disabled) {
        super(master, lock, userId);
        super(master, new SecureSettingsServiceNameResolver(master.getContext(), userId,
                Settings.Secure.AUTOFILL_SERVICE), lock, userId);

        mRequestsHistory = requestsHistory;
        mUiLatencyHistory = uiLatencyHistory;
@@ -190,11 +192,6 @@ final class AutofillManagerServiceImpl
        return mInfo.getServiceInfo();
    }

    @Override // from PerUserSystemService
    protected String getDefaultComponentName() {
        return getComponentNameFromSettings();
    }

    @Nullable
    String[] getUrlBarResourceIdsForCompatMode(@NonNull String packageName) {
        return mAutofillCompatState.getUrlBarResourceIds(packageName, mUserId);
@@ -852,8 +849,6 @@ final class AutofillManagerServiceImpl
            pw.print(prefix); pw.print("Service Label: "); pw.println(getServiceLabelLocked());
            pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked());
        }
        pw.print(prefix); pw.print("Component from settings: ");
            pw.println(getComponentNameFromSettings());
        pw.print(prefix); pw.print("Default component: "); pw.println(getContext()
                .getString(R.string.config_defaultAutofillService));
        pw.print(prefix); pw.print("Field classification enabled: ");
+6 −4
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ import java.util.List;
 * <ul>
 *   <li>Disabling the service when {@link UserManager} restrictions change.
 *   <li>Refreshing the service when its underlying
 *   {@link #getServiceSettingsProperty() Settings property} changed.
 *   {@link #getSettingsProperty() Settings property} changed.
 *   <li>Calling the service when other Settings properties changed.
 * </ul>
 *
@@ -214,7 +214,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
    }

    /**
     * Temporary sets the service implementation.
     * Temporarily sets the service implementation.
     *
     * <p>Typically used by Shell command and/or CTS tests.
     *
@@ -473,8 +473,10 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
            pw.print(" Verbose: "); pw.println(realVerbose);
            pw.print(prefix); pw.print("Disabled users: "); pw.println(mDisabledUsers);
            pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService);
            pw.print(prefix); pw.print("Settings property: "); pw.println(
                    getServiceSettingsProperty());
            final String settingsProperty = getServiceSettingsProperty();
            if (settingsProperty != null) {
                pw.print(prefix); pw.print("Settings property: "); pw.println(settingsProperty);
            }
            pw.print(prefix); pw.print("Cached services: ");
            if (size == 0) {
                pw.println("none");
+14 −103
Original line number Diff line number Diff line
@@ -26,17 +26,12 @@ import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
import android.util.TimeUtils;

import com.android.internal.annotations.GuardedBy;

@@ -54,15 +49,14 @@ import java.io.PrintWriter;
public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSystemService<S, M>,
        M extends AbstractMasterSystemService<M, S>> {

    /** Handler message to {@link #resetTemporaryServiceLocked()} */
    private static final int MSG_RESET_TEMPORARY_SERVICE = 0;

    protected final @UserIdInt int mUserId;
    protected final Object mLock;
    protected final String mTag = getClass().getSimpleName();

    protected final M mMaster;

    private final ServiceNameResolver mServiceNameResolver;

    /**
     * Whether service was disabled for user due to {@link UserManager} restrictions.
     */
@@ -78,29 +72,13 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
    @GuardedBy("mLock")
    private ServiceInfo mServiceInfo;

    /**
     * Temporary service name set by {@link #setTemporaryServiceLocked(String, int)}.
     *
     * <p>Typically used by Shell command and/or CTS tests.
     */
    @GuardedBy("mLock")
    private String mTemporaryServiceName;

    /**
     * When the temporary service will expire (and reset back to the default).
     */
    @GuardedBy("mLock")
    private long mTemporaryServiceExpiration;

    /**
     * Handler used to reset the temporary service name.
     */
    @GuardedBy("mLock")
    private Handler mTemporaryHandler;

    protected AbstractPerUserSystemService(@NonNull M master, @NonNull Object lock,
    protected AbstractPerUserSystemService(@NonNull M master,
            @NonNull ServiceNameResolver serviceNamer, @NonNull Object lock,
            @UserIdInt int userId) {
        mMaster = master;
        mServiceNameResolver = serviceNamer;
        mServiceNameResolver
                .setOnTemporaryServiceNameChangedCallback(() -> updateLocked(mDisabled));
        mLock = lock;
        mUserId = userId;
    }
@@ -219,43 +197,18 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
    }

    /**
     * Gets the current name of the service, which is either the
     *  {@link #getDefaultComponentName() default service} or the
     * Gets the current name of the service, which is either the default service or the
     *  {@link #setTemporaryServiceLocked(String, int) temporary one}.
     */
    protected final String getComponentNameLocked() {
        if (mTemporaryServiceName != null) {
            // Always log it, as it should only be used on CTS or during development
            Slog.w(mTag, "getComponentName(): using temporary name " + mTemporaryServiceName);
            return mTemporaryServiceName;
        }
        return getDefaultComponentName();
    }

    /**
     * Gets the name of the default component for the service.
     *
     * <p>Typically implemented by returning {@link #getComponentNameFromSettings()} or by using
     * a string from the system resources.
     */
    @Nullable
    protected abstract String getDefaultComponentName();

    /**
     * Gets this name of the remote service this service binds to as defined by {@link Settings}.
     */
    @Nullable
    protected final String getComponentNameFromSettings() {
        final String property = mMaster.getServiceSettingsProperty();
        return property == null ? null : Settings.Secure
                .getStringForUser(getContext().getContentResolver(), property, mUserId);
        return mServiceNameResolver.getServiceNameLocked();
    }

    /**
     * Checks whether the current service for the user was temporarily set.
     */
    public final boolean isTemporaryServiceSetLocked() {
        return mTemporaryServiceName != null;
        return mServiceNameResolver.isTemporaryLocked();
    }

    /**
@@ -266,49 +219,14 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
     * to the default component after this timeout expires).
     */
    protected final void setTemporaryServiceLocked(@NonNull String componentName, int durationMs) {
        mTemporaryServiceName = componentName;

        if (mTemporaryHandler == null) {
            mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == MSG_RESET_TEMPORARY_SERVICE) {
                        synchronized (mLock) {
                            resetTemporaryServiceLocked();
                        }
                    } else {
                        Slog.wtf(mTag, "invalid handler msg: " + msg);
                    }
                }
            };
        } else {
            removeResetTemporaryServiceMessageLocked();
        }
        mTemporaryServiceExpiration = SystemClock.elapsedRealtime() + durationMs;
        mTemporaryHandler.sendEmptyMessageDelayed(MSG_RESET_TEMPORARY_SERVICE, durationMs);

        updateLocked(mDisabled);
    }

    private void removeResetTemporaryServiceMessageLocked() {
        if (mMaster.verbose) {
            Slog.v(mTag, "setTemporaryServiceLocked(): removing old message");
        }
        // NOTE: caller should already have checked it
        mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
        mServiceNameResolver.setTemporaryServiceLocked(componentName, durationMs);
    }

    /**
     * Resets the temporary service implementation to the default component.
     */
    protected final void resetTemporaryServiceLocked() {
        Slog.i(mTag, "resetting temporary service from " + mTemporaryServiceName);
        mTemporaryServiceName = null;
        if (mTemporaryHandler != null) {
            removeResetTemporaryServiceMessageLocked();
            mTemporaryHandler = null;
        }
        updateLocked(mDisabled);
        mServiceNameResolver.resetTemporaryServiceLocked();
    }

    /**
@@ -401,14 +319,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
            pw.print(prefix); pw.print("Service UID: ");
            pw.println(mServiceInfo.applicationInfo.uid);
        }
        if (mTemporaryServiceName != null) {
            pw.print(prefix); pw.print("Temporary service name: "); pw.print(mTemporaryServiceName);
            final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime();
            pw.print(" (expires in "); TimeUtils.formatDuration(ttl, pw); pw.println(")");
            pw.print(prefix); pw.print(prefix);
            pw.print("Default service name: "); pw.println(getDefaultComponentName());
        } else {
            pw.print(prefix); pw.print("Service name: "); pw.println(getDefaultComponentName());
        }
        pw.print(prefix); pw.print("Name resolver: "); mServiceNameResolver.dumpShortLocked(pw);
        pw.println();
    }
}
+170 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.infra;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Slog;
import android.util.TimeUtils;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;

/**
 * Gets the service name using a framework resources, temporarily changing the service if necessary
 * (typically during CTS tests or service development).
 *
 * @hide
 */
public final class FrameworkResourcesServiceNameResolver implements ServiceNameResolver {

    private static final String TAG = FrameworkResourcesServiceNameResolver.class.getSimpleName();

    /** Handler message to {@link #resetTemporaryServiceLocked()} */
    private static final int MSG_RESET_TEMPORARY_SERVICE = 0;

    private final @NonNull Context mContext;
    private final @NonNull @UserIdInt int mUserId;
    private final @NonNull Object mLock;
    private final @StringRes int mResourceId;
    private @Nullable Runnable mOnSetCallback;

    /**
     * Temporary service name set by {@link #setTemporaryServiceLocked(String, int)}.
     *
     * <p>Typically used by Shell command and/or CTS tests.
     */
    @GuardedBy("mLock")
    @Nullable
    private String mTemporaryServiceName;

    /**
     * When the temporary service will expire (and reset back to the default).
     */
    @GuardedBy("mLock")
    private long mTemporaryServiceExpiration;

    /**
     * Handler used to reset the temporary service name.
     */
    @GuardedBy("mLock")
    private Handler mTemporaryHandler;

    public FrameworkResourcesServiceNameResolver(@NonNull Context context, @UserIdInt int userId,
            @NonNull Object lock, @StringRes int resourceId) {
        mLock = lock;
        mContext = context;
        mUserId = userId;
        mResourceId = resourceId;
    }

    @Override
    public void setOnTemporaryServiceNameChangedCallback(@NonNull Runnable callback) {
        this.mOnSetCallback = callback;
    }

    @Override
    public String getDefaultServiceName() {
        final String name = mContext.getString(mResourceId);
        return TextUtils.isEmpty(name) ? null : name;
    }

    @Override
    public String getServiceNameLocked() {
        if (mTemporaryServiceName != null) {
            // Always log it, as it should only be used on CTS or during development
            Slog.w(TAG, "getComponentName(): using temporary name " + mTemporaryServiceName);
            return mTemporaryServiceName;
        } else {
            return getDefaultServiceName();
        }
    }

    @Override
    public boolean isTemporaryLocked() {
        return mTemporaryServiceName != null;
    }

    @Override
    public void setTemporaryServiceLocked(@NonNull String componentName, int durationMs) {
        mTemporaryServiceName = componentName;

        if (mTemporaryHandler == null) {
            mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == MSG_RESET_TEMPORARY_SERVICE) {
                        synchronized (mLock) {
                            resetTemporaryServiceLocked();
                        }
                    } else {
                        Slog.wtf(TAG, "invalid handler msg: " + msg);
                    }
                }
            };
        } else {
            removeResetTemporaryServiceMessageLocked();
        }
        mTemporaryServiceExpiration = SystemClock.elapsedRealtime() + durationMs;
        mTemporaryHandler.sendEmptyMessageDelayed(MSG_RESET_TEMPORARY_SERVICE, durationMs);
        onServiceNameChanged();
    }

    @Override
    public void resetTemporaryServiceLocked() {
        Slog.i(TAG, "resetting temporary service from " + mTemporaryServiceName);
        mTemporaryServiceName = null;
        if (mTemporaryHandler != null) {
            removeResetTemporaryServiceMessageLocked();
            mTemporaryHandler = null;
        }
        onServiceNameChanged();
    }

    // TODO(b/117779333): support proto
    @Override
    public void dumpShortLocked(@NonNull PrintWriter pw) {
        pw.print("FrameworkResourcesServiceNamer: resId="); pw.print(mResourceId);
        if (mTemporaryServiceName != null) {
            pw.print(", tmpName="); pw.print(mTemporaryServiceName);
            final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime();
            pw.print(" (expires in "); TimeUtils.formatDuration(ttl, pw); pw.print(")");
            pw.print(", defaultName="); pw.println(getDefaultServiceName());
        } else {
            pw.print(", serviceName="); pw.println(getDefaultServiceName());
        }
    }

    private void onServiceNameChanged() {
        if (mOnSetCallback != null) {
            mOnSetCallback.run();
        }
    }

    private void removeResetTemporaryServiceMessageLocked() {
        // NOTE: caller should already have checked it
        mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
    }
}
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.infra;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.provider.Settings;

import java.io.PrintWriter;

/**
 * Gets the service name using a property from the {@link android.provider.Settings.Secure}
 * provider.
 *
 * @hide
 */
public final class SecureSettingsServiceNameResolver implements ServiceNameResolver {

    private final @NonNull Context mContext;
    private final @NonNull @UserIdInt int mUserId;

    @NonNull
    private final String mProperty;

    public SecureSettingsServiceNameResolver(@NonNull Context context, @UserIdInt int userId,
            @NonNull String property) {
        mContext = context;
        mUserId = userId;
        mProperty = property;
    }

    @Override
    public String getDefaultServiceName() {
        return Settings.Secure.getStringForUser(mContext.getContentResolver(), mProperty, mUserId);
    }

    // TODO(b/117779333): support proto
    @Override
    public void dumpShortLocked(@NonNull PrintWriter pw) {
        pw.print("SecureSettingsServiceNamer: prop="); pw.print(mProperty);
        pw.print(", value="); pw.println(getDefaultServiceName());
    }
}
Loading