diff --git a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
index 5253d34a38f01..d4e8f27a7b344 100644
--- a/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
+++ b/services/core/java/com/android/server/infra/FrameworkResourcesServiceNameResolver.java
@@ -19,28 +19,9 @@ import android.annotation.ArrayRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.annotation.UserIdInt;
-import android.app.AppGlobals;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
-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.SparseArray;
-import android.util.SparseBooleanArray;
-import android.util.TimeUtils;
-
-import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
/**
* Gets the service name using a framework resources, temporarily changing the service if necessary
@@ -48,259 +29,42 @@ import java.util.List;
*
* @hide
*/
-public final class FrameworkResourcesServiceNameResolver implements ServiceNameResolver {
+public final class FrameworkResourcesServiceNameResolver extends ServiceNameBaseResolver {
- private static final String TAG = FrameworkResourcesServiceNameResolver.class.getSimpleName();
-
- /** Handler message to {@link #resetTemporaryService(int)} */
- private static final int MSG_RESET_TEMPORARY_SERVICE = 0;
-
- @NonNull
- private final Context mContext;
- @NonNull
- private final Object mLock = new Object();
- @StringRes
private final int mStringResourceId;
@ArrayRes
private final int mArrayResourceId;
- private final boolean mIsMultiple;
- /**
- * Map of temporary service name list set by {@link #setTemporaryServices(int, String[], int)},
- * keyed by {@code userId}.
- *
- *
Typically used by Shell command and/or CTS tests to configure temporary services if
- * mIsMultiple is true.
- */
- @GuardedBy("mLock")
- private final SparseArray mTemporaryServiceNamesList = new SparseArray<>();
- /**
- * Map of default services that have been disabled by
- * {@link #setDefaultServiceEnabled(int, boolean)},keyed by {@code userId}.
- *
- * Typically used by Shell command and/or CTS tests.
- */
- @GuardedBy("mLock")
- private final SparseBooleanArray mDefaultServicesDisabled = new SparseBooleanArray();
- @Nullable
- private NameResolverListener mOnSetCallback;
- /**
- * 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,
@StringRes int resourceId) {
- mContext = context;
+ super(context, false);
mStringResourceId = resourceId;
mArrayResourceId = -1;
- mIsMultiple = false;
}
public FrameworkResourcesServiceNameResolver(@NonNull Context context,
@ArrayRes int resourceId, boolean isMultiple) {
+ super(context, isMultiple);
if (!isMultiple) {
throw new UnsupportedOperationException("Please use "
+ "FrameworkResourcesServiceNameResolver(context, @StringRes int) constructor "
+ "if single service mode is requested.");
}
- mContext = context;
mStringResourceId = -1;
mArrayResourceId = resourceId;
- mIsMultiple = true;
}
@Override
- public void setOnTemporaryServiceNameChangedCallback(@NonNull NameResolverListener callback) {
- synchronized (mLock) {
- this.mOnSetCallback = callback;
- }
+ public String[] readServiceNameList(int userId) {
+ return mContext.getResources().getStringArray(mArrayResourceId);
}
+ @Nullable
@Override
- public String getServiceName(@UserIdInt int userId) {
- String[] serviceNames = getServiceNameList(userId);
- return (serviceNames == null || serviceNames.length == 0) ? null : serviceNames[0];
+ public String readServiceName(int userId) {
+ return mContext.getResources().getString(mStringResourceId);
}
- @Override
- public String getDefaultServiceName(@UserIdInt int userId) {
- String[] serviceNames = getDefaultServiceNameList(userId);
- return (serviceNames == null || serviceNames.length == 0) ? null : serviceNames[0];
- }
-
- /**
- * Gets the default list of the service names for the given user.
- *
- *
Typically implemented by services which want to provide multiple backends.
- */
- @Override
- public String[] getServiceNameList(int userId) {
- synchronized (mLock) {
- String[] temporaryNames = mTemporaryServiceNamesList.get(userId);
- if (temporaryNames != null) {
- // Always log it, as it should only be used on CTS or during development
- Slog.w(TAG, "getServiceName(): using temporary name "
- + Arrays.toString(temporaryNames) + " for user " + userId);
- return temporaryNames;
- }
- final boolean disabled = mDefaultServicesDisabled.get(userId);
- if (disabled) {
- // Always log it, as it should only be used on CTS or during development
- Slog.w(TAG, "getServiceName(): temporary name not set and default disabled for "
- + "user " + userId);
- return null;
- }
- return getDefaultServiceNameList(userId);
-
- }
- }
-
- /**
- * Gets the default list of the service names for the given user.
- *
- *
Typically implemented by services which want to provide multiple backends.
- */
- @Override
- public String[] getDefaultServiceNameList(int userId) {
- synchronized (mLock) {
- if (mIsMultiple) {
- String[] serviceNameList = mContext.getResources().getStringArray(mArrayResourceId);
- // Filter out unimplemented services
- // Initialize the validated array as null because we do not know the final size.
- List validatedServiceNameList = new ArrayList<>();
- try {
- for (int i = 0; i < serviceNameList.length; i++) {
- if (TextUtils.isEmpty(serviceNameList[i])) {
- continue;
- }
- ComponentName serviceComponent = ComponentName.unflattenFromString(
- serviceNameList[i]);
- ServiceInfo serviceInfo = AppGlobals.getPackageManager().getServiceInfo(
- serviceComponent,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
- if (serviceInfo != null) {
- validatedServiceNameList.add(serviceNameList[i]);
- }
- }
- } catch (Exception e) {
- Slog.e(TAG, "Could not validate provided services.", e);
- }
- String[] validatedServiceNameArray = new String[validatedServiceNameList.size()];
- return validatedServiceNameList.toArray(validatedServiceNameArray);
- } else {
- final String name = mContext.getString(mStringResourceId);
- return TextUtils.isEmpty(name) ? new String[0] : new String[]{name};
- }
- }
- }
-
- @Override
- public boolean isConfiguredInMultipleMode() {
- return mIsMultiple;
- }
-
- @Override
- public boolean isTemporary(@UserIdInt int userId) {
- synchronized (mLock) {
- return mTemporaryServiceNamesList.get(userId) != null;
- }
- }
-
- @Override
- public void setTemporaryService(@UserIdInt int userId, @NonNull String componentName,
- int durationMs) {
- setTemporaryServices(userId, new String[]{componentName}, durationMs);
- }
-
- @Override
- public void setTemporaryServices(int userId, @NonNull String[] componentNames, int durationMs) {
- synchronized (mLock) {
- mTemporaryServiceNamesList.put(userId, componentNames);
-
- 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) {
- resetTemporaryService(userId);
- }
- } else {
- Slog.wtf(TAG, "invalid handler msg: " + msg);
- }
- }
- };
- } else {
- mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
- }
- mTemporaryServiceExpiration = SystemClock.elapsedRealtime() + durationMs;
- mTemporaryHandler.sendEmptyMessageDelayed(MSG_RESET_TEMPORARY_SERVICE, durationMs);
- for (int i = 0; i < componentNames.length; i++) {
- notifyTemporaryServiceNameChangedLocked(userId, componentNames[i],
- /* isTemporary= */ true);
- }
- }
- }
-
- @Override
- public void resetTemporaryService(@UserIdInt int userId) {
- synchronized (mLock) {
- Slog.i(TAG, "resetting temporary service for user " + userId + " from "
- + Arrays.toString(mTemporaryServiceNamesList.get(userId)));
- mTemporaryServiceNamesList.remove(userId);
- if (mTemporaryHandler != null) {
- mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
- mTemporaryHandler = null;
- }
- notifyTemporaryServiceNameChangedLocked(userId, /* newTemporaryName= */ null,
- /* isTemporary= */ false);
- }
- }
-
- @Override
- public boolean setDefaultServiceEnabled(int userId, boolean enabled) {
- synchronized (mLock) {
- final boolean currentlyEnabled = isDefaultServiceEnabledLocked(userId);
- if (currentlyEnabled == enabled) {
- Slog.i(TAG, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
- return false;
- }
- if (enabled) {
- Slog.i(TAG, "disabling default service for user " + userId);
- mDefaultServicesDisabled.removeAt(userId);
- } else {
- Slog.i(TAG, "enabling default service for user " + userId);
- mDefaultServicesDisabled.put(userId, true);
- }
- }
- return true;
- }
-
- @Override
- public boolean isDefaultServiceEnabled(int userId) {
- synchronized (mLock) {
- return isDefaultServiceEnabledLocked(userId);
- }
- }
-
- private boolean isDefaultServiceEnabledLocked(int userId) {
- return !mDefaultServicesDisabled.get(userId);
- }
-
- @Override
- public String toString() {
- synchronized (mLock) {
- return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNamesList + "]";
- }
- }
// TODO(b/117779333): support proto
@Override
@@ -314,31 +78,4 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
pw.print(mDefaultServicesDisabled.size());
}
}
-
- // TODO(b/117779333): support proto
- @Override
- public void dumpShort(@NonNull PrintWriter pw, @UserIdInt int userId) {
- synchronized (mLock) {
- final String[] temporaryNames = mTemporaryServiceNamesList.get(userId);
- if (temporaryNames != null) {
- pw.print("tmpName=");
- pw.print(Arrays.toString(temporaryNames));
- final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime();
- pw.print(" (expires in ");
- TimeUtils.formatDuration(ttl, pw);
- pw.print("), ");
- }
- pw.print("defaultName=");
- pw.print(getDefaultServiceName(userId));
- final boolean disabled = mDefaultServicesDisabled.get(userId);
- pw.println(disabled ? " (disabled)" : " (enabled)");
- }
- }
-
- private void notifyTemporaryServiceNameChangedLocked(@UserIdInt int userId,
- @Nullable String newTemporaryName, boolean isTemporary) {
- if (mOnSetCallback != null) {
- mOnSetCallback.onNameResolved(userId, newTemporaryName, isTemporary);
- }
- }
}
diff --git a/services/core/java/com/android/server/infra/SecureSettingsServiceNameResolver.java b/services/core/java/com/android/server/infra/SecureSettingsServiceNameResolver.java
index cac7f53aad664..17d75e600c366 100644
--- a/services/core/java/com/android/server/infra/SecureSettingsServiceNameResolver.java
+++ b/services/core/java/com/android/server/infra/SecureSettingsServiceNameResolver.java
@@ -19,8 +19,11 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
import java.io.PrintWriter;
+import java.util.Set;
/**
* Gets the service name using a property from the {@link android.provider.Settings.Secure}
@@ -28,21 +31,34 @@ import java.io.PrintWriter;
*
* @hide
*/
-public final class SecureSettingsServiceNameResolver implements ServiceNameResolver {
+public final class SecureSettingsServiceNameResolver extends ServiceNameBaseResolver {
+ /**
+ * The delimiter to be used to parse the secure settings string. Services must make sure
+ * that this delimiter is used while adding component names to their secure setting property.
+ */
+ private static final char COMPONENT_NAME_SEPARATOR = ':';
- private final @NonNull Context mContext;
+ private final TextUtils.SimpleStringSplitter mStringColonSplitter =
+ new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
@NonNull
private final String mProperty;
public SecureSettingsServiceNameResolver(@NonNull Context context, @NonNull String property) {
- mContext = context;
- mProperty = property;
+ this(context, property, /*isMultiple*/false);
}
- @Override
- public String getDefaultServiceName(@UserIdInt int userId) {
- return Settings.Secure.getStringForUser(mContext.getContentResolver(), mProperty, userId);
+ /**
+ *
+ * @param context the context required to retrieve the secure setting value
+ * @param property name of the secure setting key
+ * @param isMultiple true if the system service using this resolver needs to connect to
+ * multiple remote services, false otherwise
+ */
+ public SecureSettingsServiceNameResolver(@NonNull Context context, @NonNull String property,
+ boolean isMultiple) {
+ super(context, isMultiple);
+ mProperty = property;
}
// TODO(b/117779333): support proto
@@ -61,4 +77,34 @@ public final class SecureSettingsServiceNameResolver implements ServiceNameResol
public String toString() {
return "SecureSettingsServiceNameResolver[" + mProperty + "]";
}
+
+ @Override
+ public String[] readServiceNameList(int userId) {
+ return parseColonDelimitedServiceNames(
+ Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), mProperty, userId));
+ }
+
+ @Override
+ public String readServiceName(int userId) {
+ return Settings.Secure.getStringForUser(
+ mContext.getContentResolver(), mProperty, userId);
+ }
+
+ private String[] parseColonDelimitedServiceNames(String serviceNames) {
+ final Set delimitedServices = new ArraySet<>();
+ if (!TextUtils.isEmpty(serviceNames)) {
+ final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
+ splitter.setString(serviceNames);
+ while (splitter.hasNext()) {
+ final String str = splitter.next();
+ if (TextUtils.isEmpty(str)) {
+ continue;
+ }
+ delimitedServices.add(str);
+ }
+ }
+ String[] delimitedServicesArray = new String[delimitedServices.size()];
+ return delimitedServices.toArray(delimitedServicesArray);
+ }
}
diff --git a/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
new file mode 100644
index 0000000000000..76ea05e361415
--- /dev/null
+++ b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
@@ -0,0 +1,325 @@
+/*
+ * 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.UserIdInt;
+import android.app.AppGlobals;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+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.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Gets the service name using a framework resources, temporarily changing the service if necessary
+ * (typically during CTS tests or service development).
+ *
+ * @hide
+ */
+public abstract class ServiceNameBaseResolver implements ServiceNameResolver {
+
+ private static final String TAG = ServiceNameBaseResolver.class.getSimpleName();
+
+ /** Handler message to {@link #resetTemporaryService(int)} */
+ private static final int MSG_RESET_TEMPORARY_SERVICE = 0;
+
+ @NonNull
+ protected final Context mContext;
+ @NonNull
+ protected final Object mLock = new Object();
+
+ protected final boolean mIsMultiple;
+ /**
+ * Map of temporary service name list set by {@link #setTemporaryServices(int, String[], int)},
+ * keyed by {@code userId}.
+ *
+ * Typically used by Shell command and/or CTS tests to configure temporary services if
+ * mIsMultiple is true.
+ */
+ @GuardedBy("mLock")
+ protected final SparseArray mTemporaryServiceNamesList = new SparseArray<>();
+ /**
+ * Map of default services that have been disabled by
+ * {@link #setDefaultServiceEnabled(int, boolean)},keyed by {@code userId}.
+ *
+ * Typically used by Shell command and/or CTS tests.
+ */
+ @GuardedBy("mLock")
+ protected final SparseBooleanArray mDefaultServicesDisabled = new SparseBooleanArray();
+ @Nullable
+ private NameResolverListener mOnSetCallback;
+ /**
+ * 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 ServiceNameBaseResolver(Context context, boolean isMultiple) {
+ mContext = context;
+ mIsMultiple = isMultiple;
+ }
+
+ @Override
+ public void setOnTemporaryServiceNameChangedCallback(@NonNull NameResolverListener callback) {
+ synchronized (mLock) {
+ this.mOnSetCallback = callback;
+ }
+ }
+
+ @Override
+ public String getServiceName(@UserIdInt int userId) {
+ String[] serviceNames = getServiceNameList(userId);
+ return (serviceNames == null || serviceNames.length == 0) ? null : serviceNames[0];
+ }
+
+ @Override
+ public String getDefaultServiceName(@UserIdInt int userId) {
+ String[] serviceNames = getDefaultServiceNameList(userId);
+ return (serviceNames == null || serviceNames.length == 0) ? null : serviceNames[0];
+ }
+
+ /**
+ * Gets the default list of the service names for the given user.
+ *
+ *
Typically implemented by services which want to provide multiple backends.
+ */
+ @Override
+ public String[] getServiceNameList(int userId) {
+ synchronized (mLock) {
+ String[] temporaryNames = mTemporaryServiceNamesList.get(userId);
+ if (temporaryNames != null) {
+ // Always log it, as it should only be used on CTS or during development
+ Slog.w(TAG, "getServiceName(): using temporary name "
+ + Arrays.toString(temporaryNames) + " for user " + userId);
+ return temporaryNames;
+ }
+ final boolean disabled = mDefaultServicesDisabled.get(userId);
+ if (disabled) {
+ // Always log it, as it should only be used on CTS or during development
+ Slog.w(TAG, "getServiceName(): temporary name not set and default disabled for "
+ + "user " + userId);
+ return null;
+ }
+ return getDefaultServiceNameList(userId);
+
+ }
+ }
+
+ /**
+ * Base classes must override this to read from the desired config e.g. framework resource,
+ * secure settings etc.
+ */
+ @Nullable
+ public abstract String[] readServiceNameList(int userId);
+
+ /**
+ * Base classes must override this to read from the desired config e.g. framework resource,
+ * secure settings etc.
+ */
+ @Nullable
+ public abstract String readServiceName(int userId);
+
+ /**
+ * Gets the default list of the service names for the given user.
+ *
+ *
Typically implemented by services which want to provide multiple backends.
+ */
+ @Override
+ public String[] getDefaultServiceNameList(int userId) {
+ synchronized (mLock) {
+ if (mIsMultiple) {
+ String[] serviceNameList = readServiceNameList(userId);
+ // Filter out unimplemented services
+ // Initialize the validated array as null because we do not know the final size.
+ List validatedServiceNameList = new ArrayList<>();
+ try {
+ for (int i = 0; i < serviceNameList.length; i++) {
+ if (TextUtils.isEmpty(serviceNameList[i])) {
+ continue;
+ }
+ ComponentName serviceComponent = ComponentName.unflattenFromString(
+ serviceNameList[i]);
+ ServiceInfo serviceInfo = AppGlobals.getPackageManager().getServiceInfo(
+ serviceComponent,
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId);
+ if (serviceInfo != null) {
+ validatedServiceNameList.add(serviceNameList[i]);
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not validate provided services.", e);
+ }
+ String[] validatedServiceNameArray = new String[validatedServiceNameList.size()];
+ return validatedServiceNameList.toArray(validatedServiceNameArray);
+ } else {
+ final String name = readServiceName(userId);
+ return TextUtils.isEmpty(name) ? new String[0] : new String[]{name};
+ }
+ }
+ }
+
+ @Override
+ public boolean isConfiguredInMultipleMode() {
+ return mIsMultiple;
+ }
+
+ @Override
+ public boolean isTemporary(@UserIdInt int userId) {
+ synchronized (mLock) {
+ return mTemporaryServiceNamesList.get(userId) != null;
+ }
+ }
+
+ @Override
+ public void setTemporaryService(@UserIdInt int userId, @NonNull String componentName,
+ int durationMs) {
+ setTemporaryServices(userId, new String[]{componentName}, durationMs);
+ }
+
+ @Override
+ public void setTemporaryServices(int userId, @NonNull String[] componentNames, int durationMs) {
+ synchronized (mLock) {
+ mTemporaryServiceNamesList.put(userId, componentNames);
+
+ 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) {
+ resetTemporaryService(userId);
+ }
+ } else {
+ Slog.wtf(TAG, "invalid handler msg: " + msg);
+ }
+ }
+ };
+ } else {
+ mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
+ }
+ mTemporaryServiceExpiration = SystemClock.elapsedRealtime() + durationMs;
+ mTemporaryHandler.sendEmptyMessageDelayed(MSG_RESET_TEMPORARY_SERVICE, durationMs);
+ for (int i = 0; i < componentNames.length; i++) {
+ notifyTemporaryServiceNameChangedLocked(userId, componentNames[i],
+ /* isTemporary= */ true);
+ }
+ }
+ }
+
+ @Override
+ public void resetTemporaryService(@UserIdInt int userId) {
+ synchronized (mLock) {
+ Slog.i(TAG, "resetting temporary service for user " + userId + " from "
+ + Arrays.toString(mTemporaryServiceNamesList.get(userId)));
+ mTemporaryServiceNamesList.remove(userId);
+ if (mTemporaryHandler != null) {
+ mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
+ mTemporaryHandler = null;
+ }
+ notifyTemporaryServiceNameChangedLocked(userId, /* newTemporaryName= */ null,
+ /* isTemporary= */ false);
+ }
+ }
+
+ @Override
+ public boolean setDefaultServiceEnabled(int userId, boolean enabled) {
+ synchronized (mLock) {
+ final boolean currentlyEnabled = isDefaultServiceEnabledLocked(userId);
+ if (currentlyEnabled == enabled) {
+ Slog.i(TAG, "setDefaultServiceEnabled(" + userId + "): already " + enabled);
+ return false;
+ }
+ if (enabled) {
+ Slog.i(TAG, "disabling default service for user " + userId);
+ mDefaultServicesDisabled.removeAt(userId);
+ } else {
+ Slog.i(TAG, "enabling default service for user " + userId);
+ mDefaultServicesDisabled.put(userId, true);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isDefaultServiceEnabled(int userId) {
+ synchronized (mLock) {
+ return isDefaultServiceEnabledLocked(userId);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean isDefaultServiceEnabledLocked(int userId) {
+ return !mDefaultServicesDisabled.get(userId);
+ }
+
+ @Override
+ public String toString() {
+ synchronized (mLock) {
+ return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNamesList + "]";
+ }
+ }
+
+ // TODO(b/117779333): support proto
+ @Override
+ public void dumpShort(@NonNull PrintWriter pw, @UserIdInt int userId) {
+ synchronized (mLock) {
+ final String[] temporaryNames = mTemporaryServiceNamesList.get(userId);
+ if (temporaryNames != null) {
+ pw.print("tmpName=");
+ pw.print(Arrays.toString(temporaryNames));
+ final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime();
+ pw.print(" (expires in ");
+ TimeUtils.formatDuration(ttl, pw);
+ pw.print("), ");
+ }
+ pw.print("defaultName=");
+ pw.print(getDefaultServiceName(userId));
+ final boolean disabled = mDefaultServicesDisabled.get(userId);
+ pw.println(disabled ? " (disabled)" : " (enabled)");
+ }
+ }
+
+ private void notifyTemporaryServiceNameChangedLocked(@UserIdInt int userId,
+ @Nullable String newTemporaryName, boolean isTemporary) {
+ if (mOnSetCallback != null) {
+ mOnSetCallback.onNameResolved(userId, newTemporaryName, isTemporary);
+ }
+ }
+}