Merge "Revert "Adding multiple provider support in AbstractMasterSystem..."" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
68688e2e19
@@ -4130,9 +4130,9 @@
|
||||
This service must be trusted, as it can be activated without explicit consent of the user.
|
||||
If no service with the specified name exists on the device, cloudsearch will be disabled.
|
||||
Example: "com.android.intelligence/.CloudSearchService"
|
||||
config_defaultCloudSearchServices is for the multiple provider case.
|
||||
config_defaultCloudSearchService is for the single provider case.
|
||||
-->
|
||||
<string-array name="config_defaultCloudSearchServices"></string-array>
|
||||
<string name="config_defaultCloudSearchService" translatable="false"></string>
|
||||
|
||||
<!-- The package name for the system's translation service.
|
||||
This service must be trusted, as it can be activated without explicit consent of the user.
|
||||
|
||||
@@ -3676,7 +3676,7 @@
|
||||
<java-symbol type="string" name="notification_channel_network_status" />
|
||||
<java-symbol type="string" name="notification_channel_network_alerts" />
|
||||
<java-symbol type="string" name="notification_channel_network_available" />
|
||||
<java-symbol type="array" name="config_defaultCloudSearchServices" />
|
||||
<java-symbol type="string" name="config_defaultCloudSearchService" />
|
||||
<java-symbol type="string" name="notification_channel_vpn" />
|
||||
<java-symbol type="string" name="notification_channel_device_admin" />
|
||||
<java-symbol type="string" name="notification_channel_alerts" />
|
||||
|
||||
@@ -43,8 +43,6 @@ import com.android.server.infra.FrameworkResourcesServiceNameResolver;
|
||||
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -64,7 +62,7 @@ public class CloudSearchManagerService extends
|
||||
|
||||
public CloudSearchManagerService(Context context) {
|
||||
super(context, new FrameworkResourcesServiceNameResolver(context,
|
||||
R.array.config_defaultCloudSearchServices, true), null,
|
||||
R.string.config_defaultCloudSearchService), null,
|
||||
PACKAGE_UPDATE_POLICY_NO_REFRESH | PACKAGE_RESTART_POLICY_NO_REFRESH);
|
||||
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
|
||||
mContext = context;
|
||||
@@ -72,25 +70,7 @@ public class CloudSearchManagerService extends
|
||||
|
||||
@Override
|
||||
protected CloudSearchPerUserService newServiceLocked(int resolvedUserId, boolean disabled) {
|
||||
return new CloudSearchPerUserService(this, mLock, resolvedUserId, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<CloudSearchPerUserService> newServiceListLocked(int resolvedUserId,
|
||||
boolean disabled, String[] serviceNames) {
|
||||
if (serviceNames == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<CloudSearchPerUserService> serviceList =
|
||||
new ArrayList<>(serviceNames.length);
|
||||
for (int i = 0; i < serviceNames.length; i++) {
|
||||
if (serviceNames[i] == null) {
|
||||
continue;
|
||||
}
|
||||
serviceList.add(new CloudSearchPerUserService(this, mLock, resolvedUserId,
|
||||
serviceNames[i]));
|
||||
}
|
||||
return serviceList;
|
||||
return new CloudSearchPerUserService(this, mLock, resolvedUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,28 +111,19 @@ public class CloudSearchManagerService extends
|
||||
@NonNull ICloudSearchManagerCallback callBack) {
|
||||
searchRequest.setSource(
|
||||
mContext.getPackageManager().getNameForUid(Binder.getCallingUid()));
|
||||
runForUser("search", (service) -> {
|
||||
synchronized (service.mLock) {
|
||||
service.onSearchLocked(searchRequest, callBack);
|
||||
}
|
||||
});
|
||||
runForUserLocked("search", searchRequest.getRequestId(), (service) ->
|
||||
service.onSearchLocked(searchRequest, callBack));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnResults(IBinder token, String requestId, SearchResponse response) {
|
||||
runForUser("returnResults", (service) -> {
|
||||
synchronized (service.mLock) {
|
||||
service.onReturnResultsLocked(token, requestId, response);
|
||||
}
|
||||
});
|
||||
runForUserLocked("returnResults", requestId, (service) ->
|
||||
service.onReturnResultsLocked(token, requestId, response));
|
||||
}
|
||||
|
||||
public void destroy(@NonNull SearchRequest searchRequest) {
|
||||
runForUser("destroyCloudSearchSession", (service) -> {
|
||||
synchronized (service.mLock) {
|
||||
service.onDestroyLocked(searchRequest.getRequestId());
|
||||
}
|
||||
});
|
||||
runForUserLocked("destroyCloudSearchSession", searchRequest.getRequestId(),
|
||||
(service) -> service.onDestroyLocked(searchRequest.getRequestId()));
|
||||
}
|
||||
|
||||
public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
|
||||
@@ -163,7 +134,8 @@ public class CloudSearchManagerService extends
|
||||
.exec(this, in, out, err, args, callback, resultReceiver);
|
||||
}
|
||||
|
||||
private void runForUser(@NonNull final String func,
|
||||
private void runForUserLocked(@NonNull final String func,
|
||||
@NonNull final String requestId,
|
||||
@NonNull final Consumer<CloudSearchPerUserService> c) {
|
||||
ActivityManagerInternal am = LocalServices.getService(ActivityManagerInternal.class);
|
||||
final int userId = am.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
|
||||
@@ -171,7 +143,7 @@ public class CloudSearchManagerService extends
|
||||
null, null);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "runForUser:" + func + " from pid=" + Binder.getCallingPid()
|
||||
Slog.d(TAG, "runForUserLocked:" + func + " from pid=" + Binder.getCallingPid()
|
||||
+ ", uid=" + Binder.getCallingUid());
|
||||
}
|
||||
Context ctx = getContext();
|
||||
@@ -188,11 +160,8 @@ public class CloudSearchManagerService extends
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mLock) {
|
||||
final List<CloudSearchPerUserService> services =
|
||||
getServiceListForUserLocked(userId);
|
||||
for (int i = 0; i < services.size(); i++) {
|
||||
c.accept(services.get(i));
|
||||
}
|
||||
final CloudSearchPerUserService service = getServiceForUserLocked(userId);
|
||||
c.accept(service);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
|
||||
@@ -54,12 +54,7 @@ public class CloudSearchManagerServiceShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
final int duration = Integer.parseInt(getNextArgRequired());
|
||||
String[] services = serviceName.split(";");
|
||||
if (services.length == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
mService.setTemporaryServices(userId, services, duration);
|
||||
}
|
||||
mService.setTemporaryService(userId, serviceName, duration);
|
||||
pw.println("CloudSearchService temporarily set to " + serviceName
|
||||
+ " for " + duration + "ms");
|
||||
break;
|
||||
|
||||
@@ -49,8 +49,6 @@ public class CloudSearchPerUserService extends
|
||||
@GuardedBy("mLock")
|
||||
private final CircularQueue<String, CloudSearchCallbackInfo> mCallbackQueue =
|
||||
new CircularQueue<>(QUEUE_SIZE);
|
||||
private final String mServiceName;
|
||||
private final ComponentName mRemoteComponentName;
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
private RemoteCloudSearchService mRemoteService;
|
||||
@@ -62,10 +60,8 @@ public class CloudSearchPerUserService extends
|
||||
private boolean mZombie;
|
||||
|
||||
protected CloudSearchPerUserService(CloudSearchManagerService master,
|
||||
Object lock, int userId, String serviceName) {
|
||||
Object lock, int userId) {
|
||||
super(master, lock, userId);
|
||||
mServiceName = serviceName;
|
||||
mRemoteComponentName = ComponentName.unflattenFromString(mServiceName);
|
||||
}
|
||||
|
||||
@Override // from PerUserSystemService
|
||||
@@ -112,7 +108,7 @@ public class CloudSearchPerUserService extends
|
||||
? searchRequest.getSearchConstraints().getString(
|
||||
SearchRequest.CONSTRAINT_SEARCH_PROVIDER_FILTER) : "";
|
||||
|
||||
String remoteServicePackageName = mRemoteComponentName.getPackageName();
|
||||
String remoteServicePackageName = getServiceComponentName().getPackageName();
|
||||
// By default, all providers are marked as wanted.
|
||||
boolean wantedProvider = true;
|
||||
if (filterList.length() > 0) {
|
||||
@@ -154,19 +150,11 @@ public class CloudSearchPerUserService extends
|
||||
/**
|
||||
* Used to return results back to the clients.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
public void onReturnResultsLocked(@NonNull IBinder token,
|
||||
@NonNull String requestId,
|
||||
@NonNull SearchResponse response) {
|
||||
if (mRemoteService == null) {
|
||||
return;
|
||||
}
|
||||
ICloudSearchService serviceInterface = mRemoteService.getServiceInterface();
|
||||
if (serviceInterface == null || token != serviceInterface.asBinder()) {
|
||||
return;
|
||||
}
|
||||
if (mCallbackQueue.containsKey(requestId)) {
|
||||
response.setSource(mServiceName);
|
||||
response.setSource(mRemoteService.getComponentName().getPackageName());
|
||||
final CloudSearchCallbackInfo sessionInfo = mCallbackQueue.getElement(requestId);
|
||||
try {
|
||||
if (response.getStatusCode() == SearchResponse.SEARCH_STATUS_OK) {
|
||||
@@ -175,10 +163,6 @@ public class CloudSearchPerUserService extends
|
||||
sessionInfo.mCallback.onSearchFailed(response);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
if (mMaster.debug) {
|
||||
Slog.e(TAG, "Exception in posting results");
|
||||
e.printStackTrace();
|
||||
}
|
||||
onDestroyLocked(requestId);
|
||||
}
|
||||
}
|
||||
@@ -313,7 +297,7 @@ public class CloudSearchPerUserService extends
|
||||
@Nullable
|
||||
private RemoteCloudSearchService getRemoteServiceLocked() {
|
||||
if (mRemoteService == null) {
|
||||
final String serviceName = getComponentNameForMultipleLocked(mServiceName);
|
||||
final String serviceName = getComponentNameLocked();
|
||||
if (serviceName == null) {
|
||||
if (mMaster.verbose) {
|
||||
Slog.v(TAG, "getRemoteServiceLocked(): not set");
|
||||
|
||||
@@ -48,7 +48,6 @@ import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -169,10 +168,10 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
private final SparseBooleanArray mDisabledByUserRestriction;
|
||||
|
||||
/**
|
||||
* Cache of service list per user id.
|
||||
* Cache of services per user id.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<List<S>> mServicesCacheList = new SparseArray<>();
|
||||
private final SparseArray<S> mServicesCache = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Value that determines whether the per-user service should be removed from the cache when its
|
||||
@@ -253,7 +252,8 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
mServiceNameResolver = serviceNameResolver;
|
||||
if (mServiceNameResolver != null) {
|
||||
mServiceNameResolver.setOnTemporaryServiceNameChangedCallback(
|
||||
this::onServiceNameChanged);
|
||||
(u, s, t) -> onServiceNameChanged(u, s, t));
|
||||
|
||||
}
|
||||
if (disallowProperty == null) {
|
||||
mDisabledByUserRestriction = null;
|
||||
@@ -308,7 +308,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
@Override // from SystemService
|
||||
public void onUserStopped(@NonNull TargetUser user) {
|
||||
synchronized (mLock) {
|
||||
removeCachedServiceListLocked(user.getUserIdentifier());
|
||||
removeCachedServiceLocked(user.getUserIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,58 +386,21 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
synchronized (mLock) {
|
||||
final S oldService = peekServiceForUserLocked(userId);
|
||||
if (oldService != null) {
|
||||
oldService.removeSelfFromCache();
|
||||
oldService.removeSelfFromCacheLocked();
|
||||
}
|
||||
mServiceNameResolver.setTemporaryService(userId, componentName, durationMs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily sets the service implementation.
|
||||
*
|
||||
* <p>Typically used by Shell command and/or CTS tests.
|
||||
*
|
||||
* @param componentNames list of the names of the new component
|
||||
* @param durationMs how long the change will be valid (the service will be automatically
|
||||
* reset
|
||||
* to the default component after this timeout expires).
|
||||
* @throws SecurityException if caller is not allowed to manage this service's settings.
|
||||
* @throws IllegalArgumentException if value of {@code durationMs} is higher than
|
||||
* {@link #getMaximumTemporaryServiceDurationMs()}.
|
||||
*/
|
||||
public final void setTemporaryServices(@UserIdInt int userId, @NonNull String[] componentNames,
|
||||
int durationMs) {
|
||||
Slog.i(mTag, "setTemporaryService(" + userId + ") to " + Arrays.toString(componentNames)
|
||||
+ " for " + durationMs + "ms");
|
||||
if (mServiceNameResolver == null) {
|
||||
return;
|
||||
}
|
||||
enforceCallingPermissionForManagement();
|
||||
|
||||
Objects.requireNonNull(componentNames);
|
||||
final int maxDurationMs = getMaximumTemporaryServiceDurationMs();
|
||||
if (durationMs > maxDurationMs) {
|
||||
throw new IllegalArgumentException(
|
||||
"Max duration is " + maxDurationMs + " (called with " + durationMs + ")");
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
final S oldService = peekServiceForUserLocked(userId);
|
||||
if (oldService != null) {
|
||||
oldService.removeSelfFromCache();
|
||||
}
|
||||
mServiceNameResolver.setTemporaryServices(userId, componentNames, durationMs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the default service should be used.
|
||||
*
|
||||
* <p>Typically used during CTS tests to make sure only the default service doesn't interfere
|
||||
* with the test results.
|
||||
*
|
||||
* @return whether the enabled state changed.
|
||||
* @throws SecurityException if caller is not allowed to manage this service's settings.
|
||||
*
|
||||
* @return whether the enabled state changed.
|
||||
*/
|
||||
public final boolean setDefaultServiceEnabled(@UserIdInt int userId, boolean enabled) {
|
||||
Slog.i(mTag, "setDefaultServiceEnabled() for userId " + userId + ": " + enabled);
|
||||
@@ -457,7 +420,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
|
||||
final S oldService = peekServiceForUserLocked(userId);
|
||||
if (oldService != null) {
|
||||
oldService.removeSelfFromCache();
|
||||
oldService.removeSelfFromCacheLocked();
|
||||
}
|
||||
|
||||
// Must update the service on cache so its initialization code is triggered
|
||||
@@ -537,21 +500,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
@Nullable
|
||||
protected abstract S newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled);
|
||||
|
||||
/**
|
||||
* Creates a new service list that will be added to the cache.
|
||||
*
|
||||
* @param resolvedUserId the resolved user id for the service.
|
||||
* @param disabled whether the service is currently disabled (due to {@link UserManager}
|
||||
* restrictions).
|
||||
* @return a new instance.
|
||||
*/
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
protected List<S> newServiceListLocked(@UserIdInt int resolvedUserId, boolean disabled,
|
||||
String[] serviceNames) {
|
||||
throw new UnsupportedOperationException("newServiceListLocked not implemented. ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service for extra Settings changes (i.e., other than
|
||||
* {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
|
||||
@@ -568,6 +516,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
* <p><b>NOTE: </p>it doesn't need to register for
|
||||
* {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE} or
|
||||
* {@link #getServiceSettingsProperty()}.
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
|
||||
@@ -578,7 +527,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
* Callback for Settings changes that were registered though
|
||||
* {@link #registerForExtraSettingsChanges(ContentResolver, ContentObserver)}.
|
||||
*
|
||||
* @param userId user associated with the change
|
||||
* @param userId user associated with the change
|
||||
* @param property Settings property changed.
|
||||
*/
|
||||
protected void onSettingsChanged(@UserIdInt int userId, @NonNull String property) {
|
||||
@@ -590,38 +539,18 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
protected S getServiceForUserLocked(@UserIdInt int userId) {
|
||||
List<S> services = getServiceListForUserLocked(userId);
|
||||
return services == null || services.size() == 0 ? null : services.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service instance list for a user, creating instances if not present in the cache.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected List<S> getServiceListForUserLocked(@UserIdInt int userId) {
|
||||
final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, false, false, null, null);
|
||||
List<S> services = mServicesCacheList.get(resolvedUserId);
|
||||
if (services == null || services.size() == 0) {
|
||||
S service = mServicesCache.get(resolvedUserId);
|
||||
if (service == null) {
|
||||
final boolean disabled = isDisabledLocked(userId);
|
||||
if (mServiceNameResolver == null) {
|
||||
return null;
|
||||
}
|
||||
if (mServiceNameResolver.isConfiguredInMultipleMode()) {
|
||||
services = newServiceListLocked(resolvedUserId, disabled,
|
||||
mServiceNameResolver.getServiceNameList(userId));
|
||||
} else {
|
||||
services = new ArrayList<>();
|
||||
services.add(newServiceLocked(resolvedUserId, disabled));
|
||||
}
|
||||
service = newServiceLocked(resolvedUserId, disabled);
|
||||
if (!disabled) {
|
||||
for (int i = 0; i < services.size(); i++) {
|
||||
onServiceEnabledLocked(services.get(i), resolvedUserId);
|
||||
}
|
||||
onServiceEnabledLocked(service, resolvedUserId);
|
||||
}
|
||||
mServicesCacheList.put(userId, services);
|
||||
mServicesCache.put(userId, service);
|
||||
}
|
||||
return services;
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -631,20 +560,9 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
protected S peekServiceForUserLocked(@UserIdInt int userId) {
|
||||
List<S> serviceList = peekServiceListForUserLocked(userId);
|
||||
return serviceList == null || serviceList.size() == 0 ? null : serviceList.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the <b>existing</b> service instance for a user, returning {@code null} if not already
|
||||
* present in the cache.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
protected List<S> peekServiceListForUserLocked(@UserIdInt int userId) {
|
||||
final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
|
||||
Binder.getCallingUid(), userId, false, false, null, null);
|
||||
return mServicesCacheList.get(resolvedUserId);
|
||||
return mServicesCache.get(resolvedUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -652,59 +570,36 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void updateCachedServiceLocked(@UserIdInt int userId) {
|
||||
updateCachedServiceListLocked(userId, isDisabledLocked(userId));
|
||||
updateCachedServiceLocked(userId, isDisabledLocked(userId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the service is disabled (through {@link UserManager} restrictions) for the
|
||||
* given user.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected boolean isDisabledLocked(@UserIdInt int userId) {
|
||||
return mDisabledByUserRestriction != null && mDisabledByUserRestriction.get(userId);
|
||||
return mDisabledByUserRestriction == null ? false : mDisabledByUserRestriction.get(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a cached service for a given user.
|
||||
*
|
||||
* @param userId user handle.
|
||||
* @param userId user handle.
|
||||
* @param disabled whether the user is disabled.
|
||||
* @return service for the user.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
|
||||
final S service = getServiceForUserLocked(userId);
|
||||
updateCachedServiceListLocked(userId, disabled);
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a cached service for a given user.
|
||||
*
|
||||
* @param userId user handle.
|
||||
* @param disabled whether the user is disabled.
|
||||
* @return service for the user.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected List<S> updateCachedServiceListLocked(@UserIdInt int userId, boolean disabled) {
|
||||
final List<S> services = getServiceListForUserLocked(userId);
|
||||
if (services == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < services.size(); i++) {
|
||||
S service = services.get(i);
|
||||
if (service != null) {
|
||||
synchronized (service.mLock) {
|
||||
service.updateLocked(disabled);
|
||||
if (!service.isEnabledLocked()) {
|
||||
removeCachedServiceListLocked(userId);
|
||||
} else {
|
||||
onServiceEnabledLocked(services.get(i), userId);
|
||||
}
|
||||
}
|
||||
if (service != null) {
|
||||
service.updateLocked(disabled);
|
||||
if (!service.isEnabledLocked()) {
|
||||
removeCachedServiceLocked(userId);
|
||||
} else {
|
||||
onServiceEnabledLocked(service, userId);
|
||||
}
|
||||
}
|
||||
return services;
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -724,32 +619,28 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
* <p>By default doesn't do anything, but can be overridden by subclasses.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@GuardedBy("mLock")
|
||||
protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a cached service list for a given user.
|
||||
* Removes a cached service for a given user.
|
||||
*
|
||||
* @return the removed service.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
protected final List<S> removeCachedServiceListLocked(@UserIdInt int userId) {
|
||||
final List<S> services = peekServiceListForUserLocked(userId);
|
||||
if (services != null) {
|
||||
mServicesCacheList.delete(userId);
|
||||
for (int i = 0; i < services.size(); i++) {
|
||||
onServiceRemoved(services.get(i), userId);
|
||||
}
|
||||
protected final S removeCachedServiceLocked(@UserIdInt int userId) {
|
||||
final S service = peekServiceForUserLocked(userId);
|
||||
if (service != null) {
|
||||
mServicesCache.delete(userId);
|
||||
onServiceRemoved(service, userId);
|
||||
}
|
||||
return services;
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the package that provides the service for the given user is being updated.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void onServicePackageUpdatingLocked(@UserIdInt int userId) {
|
||||
if (verbose) Slog.v(mTag, "onServicePackageUpdatingLocked(" + userId + ")");
|
||||
}
|
||||
@@ -757,7 +648,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
/**
|
||||
* Called after the package that provides the service for the given user is being updated.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void onServicePackageUpdatedLocked(@UserIdInt int userId) {
|
||||
if (verbose) Slog.v(mTag, "onServicePackageUpdated(" + userId + ")");
|
||||
}
|
||||
@@ -765,7 +655,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
/**
|
||||
* Called after the package data that provides the service for the given user is cleared.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void onServicePackageDataClearedLocked(@UserIdInt int userId) {
|
||||
if (verbose) Slog.v(mTag, "onServicePackageDataCleared(" + userId + ")");
|
||||
}
|
||||
@@ -773,7 +662,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
/**
|
||||
* Called after the package that provides the service for the given user is restarted.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void onServicePackageRestartedLocked(@UserIdInt int userId) {
|
||||
if (verbose) Slog.v(mTag, "onServicePackageRestarted(" + userId + ")");
|
||||
}
|
||||
@@ -791,31 +679,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
* <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call
|
||||
* that same method, or {@code super.onServiceNameChanged()}.
|
||||
*
|
||||
* @param userId user handle.
|
||||
* @param userId user handle.
|
||||
* @param serviceName the new service name.
|
||||
* @param isTemporary whether the new service is temporary.
|
||||
*/
|
||||
protected void onServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName,
|
||||
boolean isTemporary) {
|
||||
synchronized (mLock) {
|
||||
updateCachedServiceListLocked(userId, isDisabledLocked(userId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service name list has changed (typically when using temporary services).
|
||||
*
|
||||
* <p>By default, it calls {@link #updateCachedServiceLocked(int)}; subclasses must either call
|
||||
* that same method, or {@code super.onServiceNameChanged()}.
|
||||
*
|
||||
* @param userId user handle.
|
||||
* @param serviceNames the new service name list.
|
||||
* @param isTemporary whether the new service is temporary.
|
||||
*/
|
||||
protected void onServiceNameListChanged(@UserIdInt int userId, @Nullable String[] serviceNames,
|
||||
boolean isTemporary) {
|
||||
synchronized (mLock) {
|
||||
updateCachedServiceListLocked(userId, isDisabledLocked(userId));
|
||||
updateCachedServiceLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,12 +695,9 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void visitServicesLocked(@NonNull Visitor<S> visitor) {
|
||||
final int size = mServicesCacheList.size();
|
||||
final int size = mServicesCache.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
List<S> services = mServicesCacheList.valueAt(i);
|
||||
for (int j = 0; j < services.size(); j++) {
|
||||
visitor.visit(services.get(j));
|
||||
}
|
||||
visitor.visit(mServicesCache.valueAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -838,7 +706,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected void clearCacheLocked() {
|
||||
mServicesCacheList.clear();
|
||||
mServicesCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -889,7 +757,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
}
|
||||
|
||||
// TODO(b/117779333): support proto
|
||||
@GuardedBy("mLock")
|
||||
protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
|
||||
boolean realDebug = debug;
|
||||
boolean realVerbose = verbose;
|
||||
@@ -898,64 +765,40 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
try {
|
||||
// Temporarily turn on full logging;
|
||||
debug = verbose = true;
|
||||
final int size = mServicesCacheList.size();
|
||||
pw.print(prefix);
|
||||
pw.print("Debug: ");
|
||||
pw.print(realDebug);
|
||||
pw.print(" Verbose: ");
|
||||
pw.println(realVerbose);
|
||||
pw.print("Package policy flags: ");
|
||||
pw.println(mServicePackagePolicyFlags);
|
||||
final int size = mServicesCache.size();
|
||||
pw.print(prefix); pw.print("Debug: "); pw.print(realDebug);
|
||||
pw.print(" Verbose: "); pw.println(realVerbose);
|
||||
pw.print("Package policy flags: "); pw.println(mServicePackagePolicyFlags);
|
||||
if (mUpdatingPackageNames != null) {
|
||||
pw.print("Packages being updated: ");
|
||||
pw.println(mUpdatingPackageNames);
|
||||
pw.print("Packages being updated: "); pw.println(mUpdatingPackageNames);
|
||||
}
|
||||
dumpSupportedUsers(pw, prefix);
|
||||
if (mServiceNameResolver != null) {
|
||||
pw.print(prefix);
|
||||
pw.print("Name resolver: ");
|
||||
mServiceNameResolver.dumpShort(pw);
|
||||
pw.println();
|
||||
pw.print(prefix); pw.print("Name resolver: ");
|
||||
mServiceNameResolver.dumpShort(pw); pw.println();
|
||||
final List<UserInfo> users = getSupportedUsers();
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
final int userId = users.get(i).id;
|
||||
pw.print(prefix2);
|
||||
pw.print(userId);
|
||||
pw.print(": ");
|
||||
mServiceNameResolver.dumpShort(pw, userId);
|
||||
pw.println();
|
||||
pw.print(prefix2); pw.print(userId); pw.print(": ");
|
||||
mServiceNameResolver.dumpShort(pw, userId); pw.println();
|
||||
}
|
||||
}
|
||||
pw.print(prefix);
|
||||
pw.print("Users disabled by restriction: ");
|
||||
pw.print(prefix); pw.print("Users disabled by restriction: ");
|
||||
pw.println(mDisabledByUserRestriction);
|
||||
pw.print(prefix);
|
||||
pw.print("Allow instant service: ");
|
||||
pw.println(mAllowInstantService);
|
||||
pw.print(prefix); pw.print("Allow instant service: "); pw.println(mAllowInstantService);
|
||||
final String settingsProperty = getServiceSettingsProperty();
|
||||
if (settingsProperty != null) {
|
||||
pw.print(prefix);
|
||||
pw.print("Settings property: ");
|
||||
pw.println(settingsProperty);
|
||||
pw.print(prefix); pw.print("Settings property: "); pw.println(settingsProperty);
|
||||
}
|
||||
pw.print(prefix);
|
||||
pw.print("Cached services: ");
|
||||
pw.print(prefix); pw.print("Cached services: ");
|
||||
if (size == 0) {
|
||||
pw.println("none");
|
||||
} else {
|
||||
pw.println(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
pw.print(prefix);
|
||||
pw.print("Service at ");
|
||||
pw.print(i);
|
||||
pw.println(": ");
|
||||
final List<S> services = mServicesCacheList.valueAt(i);
|
||||
for (int j = 0; j < services.size(); j++) {
|
||||
S service = services.get(i);
|
||||
synchronized (service.mLock) {
|
||||
service.dumpLocked(prefix2, pw);
|
||||
}
|
||||
}
|
||||
pw.print(prefix); pw.print("Service at "); pw.print(i); pw.println(": ");
|
||||
final S service = mServicesCache.valueAt(i);
|
||||
service.dumpLocked(prefix2, pw);
|
||||
pw.println();
|
||||
}
|
||||
}
|
||||
@@ -977,7 +820,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
final int userId = getChangingUserId();
|
||||
synchronized (mLock) {
|
||||
if (mUpdatingPackageNames == null) {
|
||||
mUpdatingPackageNames = new SparseArray<String>(mServicesCacheList.size());
|
||||
mUpdatingPackageNames = new SparseArray<String>(mServicesCache.size());
|
||||
}
|
||||
mUpdatingPackageNames.put(userId, packageName);
|
||||
onServicePackageUpdatingLocked(userId);
|
||||
@@ -992,7 +835,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
+ " because package " + activePackageName
|
||||
+ " is being updated");
|
||||
}
|
||||
removeCachedServiceListLocked(userId);
|
||||
removeCachedServiceLocked(userId);
|
||||
|
||||
if ((mServicePackagePolicyFlags & PACKAGE_UPDATE_POLICY_REFRESH_EAGER)
|
||||
!= 0) {
|
||||
@@ -1058,7 +901,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
if (Intent.ACTION_PACKAGE_RESTARTED.equals(action)) {
|
||||
handleActiveServiceRestartedLocked(activePackageName, userId);
|
||||
} else {
|
||||
removeCachedServiceListLocked(userId);
|
||||
removeCachedServiceLocked(userId);
|
||||
}
|
||||
} else {
|
||||
handlePackageUpdateLocked(pkg);
|
||||
@@ -1087,7 +930,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
|
||||
private void handleActiveServiceRemoved(@UserIdInt int userId) {
|
||||
synchronized (mLock) {
|
||||
removeCachedServiceListLocked(userId);
|
||||
removeCachedServiceLocked(userId);
|
||||
}
|
||||
final String serviceSettingsProperty = getServiceSettingsProperty();
|
||||
if (serviceSettingsProperty != null) {
|
||||
@@ -1096,7 +939,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void handleActiveServiceRestartedLocked(String activePackageName,
|
||||
@UserIdInt int userId) {
|
||||
if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_NO_REFRESH) != 0) {
|
||||
@@ -1110,7 +952,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
+ " because package " + activePackageName
|
||||
+ " is being restarted");
|
||||
}
|
||||
removeCachedServiceListLocked(userId);
|
||||
removeCachedServiceLocked(userId);
|
||||
|
||||
if ((mServicePackagePolicyFlags & PACKAGE_RESTART_POLICY_REFRESH_EAGER) != 0) {
|
||||
if (debug) {
|
||||
@@ -1124,27 +966,14 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
|
||||
@Override
|
||||
public void onPackageModified(String packageName) {
|
||||
synchronized (mLock) {
|
||||
if (verbose) Slog.v(mTag, "onPackageModified(): " + packageName);
|
||||
if (verbose) Slog.v(mTag, "onPackageModified(): " + packageName);
|
||||
|
||||
if (mServiceNameResolver == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int userId = getChangingUserId();
|
||||
final String[] serviceNames = mServiceNameResolver.getDefaultServiceNameList(
|
||||
userId);
|
||||
if (serviceNames != null) {
|
||||
for (int i = 0; i < serviceNames.length; i++) {
|
||||
peekAndUpdateCachedServiceLocked(packageName, userId, serviceNames[i]);
|
||||
}
|
||||
}
|
||||
if (mServiceNameResolver == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private void peekAndUpdateCachedServiceLocked(String packageName, int userId,
|
||||
String serviceName) {
|
||||
final int userId = getChangingUserId();
|
||||
final String serviceName = mServiceNameResolver.getDefaultServiceName(userId);
|
||||
if (serviceName == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1168,7 +997,6 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private String getActiveServicePackageNameLocked() {
|
||||
final int userId = getChangingUserId();
|
||||
final S service = peekServiceForUserLocked(userId);
|
||||
@@ -1189,7 +1017,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
|
||||
};
|
||||
|
||||
// package changes
|
||||
monitor.register(getContext(), null, UserHandle.ALL, true);
|
||||
monitor.register(getContext(), null, UserHandle.ALL, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,13 +43,14 @@ import java.io.PrintWriter;
|
||||
*
|
||||
* @param <M> "main" service class.
|
||||
* @param <S> "real" service class.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSystemService<S, M>,
|
||||
M extends AbstractMasterSystemService<M, S>> {
|
||||
|
||||
@UserIdInt protected final int mUserId;
|
||||
public final Object mLock;
|
||||
protected final @UserIdInt int mUserId;
|
||||
protected final Object mLock;
|
||||
protected final String mTag = getClass().getSimpleName();
|
||||
|
||||
protected final M mMaster;
|
||||
@@ -90,14 +91,14 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
* <p><b>MUST</b> be overridden by subclasses that bind to an
|
||||
* {@link com.android.internal.infra.AbstractRemoteService}.
|
||||
*
|
||||
* @return new {@link ServiceInfo},
|
||||
* @throws NameNotFoundException if the service does not exist.
|
||||
* @throws SecurityException if the service does not have the proper permissions to
|
||||
* be bound to.
|
||||
* @throws NameNotFoundException if the service does not exist.
|
||||
* @throws SecurityException if the service does not have the proper permissions to be bound to.
|
||||
* @throws UnsupportedOperationException if subclass binds to a remote service but does not
|
||||
* overrides it.
|
||||
* overrides it.
|
||||
*
|
||||
* @return new {@link ServiceInfo},
|
||||
*/
|
||||
@NonNull protected ServiceInfo newServiceInfoLocked(
|
||||
protected @NonNull ServiceInfo newServiceInfoLocked(
|
||||
@SuppressWarnings("unused") @NonNull ComponentName serviceComponent)
|
||||
throws NameNotFoundException {
|
||||
throw new UnsupportedOperationException("not overridden");
|
||||
@@ -136,6 +137,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
* previous state.
|
||||
*
|
||||
* @param disabled whether the service is disabled (due to {@link UserManager} restrictions).
|
||||
*
|
||||
* @return whether the disabled state changed.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
@@ -152,48 +154,18 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
updateIsSetupComplete(mUserId);
|
||||
mDisabled = disabled;
|
||||
|
||||
if (mMaster.mServiceNameResolver.isConfiguredInMultipleMode()) {
|
||||
updateServiceInfoListLocked();
|
||||
} else {
|
||||
updateServiceInfoLocked();
|
||||
}
|
||||
updateServiceInfoLocked();
|
||||
return wasEnabled != isEnabledLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal reference to the service info, and returns the service's component.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected final ComponentName updateServiceInfoLocked() {
|
||||
ComponentName[] componentNames = updateServiceInfoListLocked();
|
||||
return componentNames == null || componentNames.length == 0 ? null : componentNames[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal reference to the service info, and returns the service's component.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected final ComponentName[] updateServiceInfoListLocked() {
|
||||
if (mMaster.mServiceNameResolver == null) {
|
||||
return null;
|
||||
}
|
||||
if (!mMaster.mServiceNameResolver.isConfiguredInMultipleMode()) {
|
||||
final String componentName = getComponentNameLocked();
|
||||
return new ComponentName[] { getServiceComponent(componentName) };
|
||||
}
|
||||
final String[] componentNames = mMaster.mServiceNameResolver.getServiceNameList(
|
||||
mUserId);
|
||||
ComponentName[] serviceComponents = new ComponentName[componentNames.length];
|
||||
for (int i = 0; i < componentNames.length; i++) {
|
||||
serviceComponents[i] = getServiceComponent(componentNames[i]);
|
||||
}
|
||||
return serviceComponents;
|
||||
}
|
||||
|
||||
private ComponentName getServiceComponent(String componentName) {
|
||||
synchronized (mLock) {
|
||||
ComponentName serviceComponent = null;
|
||||
if (mMaster.mServiceNameResolver != null) {
|
||||
ServiceInfo serviceInfo = null;
|
||||
ComponentName serviceComponent = null;
|
||||
final String componentName = getComponentNameLocked();
|
||||
if (!TextUtils.isEmpty(componentName)) {
|
||||
try {
|
||||
serviceComponent = ComponentName.unflattenFromString(componentName);
|
||||
@@ -224,14 +196,14 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
Slog.e(mTag, "Bad ServiceInfo for '" + componentName + "': " + e);
|
||||
mServiceInfo = null;
|
||||
}
|
||||
return serviceComponent;
|
||||
}
|
||||
return serviceComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user associated with this service.
|
||||
*/
|
||||
@UserIdInt public final int getUserId() {
|
||||
public final @UserIdInt int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
@@ -257,34 +229,15 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
|
||||
/**
|
||||
* Gets the current name of the service, which is either the default service or the
|
||||
* {@link AbstractMasterSystemService#setTemporaryService(int, String, int) temporary one}.
|
||||
* {@link AbstractMasterSystemService#setTemporaryService(int, String, int) temporary one}.
|
||||
*/
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
protected final String getComponentNameLocked() {
|
||||
protected final @Nullable String getComponentNameLocked() {
|
||||
return mMaster.mServiceNameResolver.getServiceName(mUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current name of the service, which is either the default service or the
|
||||
* {@link AbstractMasterSystemService#setTemporaryService(int, String, int) temporary one}.
|
||||
*/
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
protected final String getComponentNameForMultipleLocked(String serviceName) {
|
||||
String[] services = mMaster.mServiceNameResolver.getServiceNameList(mUserId);
|
||||
for (int i = 0; i < services.length; i++) {
|
||||
if (serviceName.equals(services[i])) {
|
||||
return services[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the current service for the user was temporarily set.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
public final boolean isTemporaryServiceSetLocked() {
|
||||
return mMaster.mServiceNameResolver.isTemporary(mUserId);
|
||||
}
|
||||
@@ -292,7 +245,6 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
/**
|
||||
* Resets the temporary service implementation to the default component.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected final void resetTemporaryServiceLocked() {
|
||||
mMaster.mServiceNameResolver.resetTemporaryService(mUserId);
|
||||
}
|
||||
@@ -316,7 +268,6 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
return mServiceInfo == null ? null : mServiceInfo.getComponentName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the of the app this service binds to, or {@code null} if the service is
|
||||
* disabled.
|
||||
@@ -352,10 +303,8 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
/**
|
||||
* Removes the service from the main service's cache.
|
||||
*/
|
||||
protected final void removeSelfFromCache() {
|
||||
synchronized (mMaster.mLock) {
|
||||
mMaster.removeCachedServiceListLocked(mUserId);
|
||||
}
|
||||
protected final void removeSelfFromCacheLocked() {
|
||||
mMaster.removeCachedServiceLocked(mUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +327,6 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
* Gets the target SDK level of the service this service binds to,
|
||||
* or {@code 0} if the service is disabled.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
public final int getTargedSdkLocked() {
|
||||
return mServiceInfo == null ? 0 : mServiceInfo.applicationInfo.targetSdkVersion;
|
||||
}
|
||||
@@ -386,7 +334,6 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
/**
|
||||
* Gets whether the device already finished setup.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
protected final boolean isSetupCompletedLocked() {
|
||||
return mSetupComplete;
|
||||
}
|
||||
@@ -401,32 +348,19 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
|
||||
// TODO(b/117779333): support proto
|
||||
@GuardedBy("mLock")
|
||||
protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
|
||||
pw.print(prefix);
|
||||
pw.print("User: ");
|
||||
pw.println(mUserId);
|
||||
pw.print(prefix); pw.print("User: "); pw.println(mUserId);
|
||||
if (mServiceInfo != null) {
|
||||
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("Service Label: "); pw.println(getServiceLabelLocked());
|
||||
pw.print(prefix); pw.print("Target SDK: "); pw.println(getTargedSdkLocked());
|
||||
}
|
||||
if (mMaster.mServiceNameResolver != null) {
|
||||
pw.print(prefix);
|
||||
pw.print("Name resolver: ");
|
||||
mMaster.mServiceNameResolver.dumpShort(pw, mUserId);
|
||||
pw.println();
|
||||
pw.print(prefix); pw.print("Name resolver: ");
|
||||
mMaster.mServiceNameResolver.dumpShort(pw, mUserId); pw.println();
|
||||
}
|
||||
pw.print(prefix);
|
||||
pw.print("Disabled by UserManager: ");
|
||||
pw.println(mDisabled);
|
||||
pw.print(prefix);
|
||||
pw.print("Setup complete: ");
|
||||
pw.println(mSetupComplete);
|
||||
pw.print(prefix); pw.print("Disabled by UserManager: "); pw.println(mDisabled);
|
||||
pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
|
||||
if (mServiceInfo != null) {
|
||||
pw.print(prefix);
|
||||
pw.print("Service UID: ");
|
||||
pw.print(prefix); pw.print("Service UID: ");
|
||||
pw.println(mServiceInfo.applicationInfo.uid);
|
||||
}
|
||||
pw.println();
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.server.infra;
|
||||
|
||||
import android.annotation.ArrayRes;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.StringRes;
|
||||
@@ -34,7 +33,6 @@ import android.util.TimeUtils;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Gets the service name using a framework resources, temporarily changing the service if necessary
|
||||
@@ -49,20 +47,20 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
/** 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;
|
||||
private final @NonNull Context mContext;
|
||||
private final @NonNull Object mLock = new Object();
|
||||
private final @StringRes int mResourceId;
|
||||
private @Nullable NameResolverListener mOnSetCallback;
|
||||
|
||||
/**
|
||||
* Map of temporary service name list set by {@link #setTemporaryServices(int, String[], int)},
|
||||
* Map of temporary service name set by {@link #setTemporaryService(int, String, int)},
|
||||
* keyed by {@code userId}.
|
||||
*
|
||||
* <p>Typically used by Shell command and/or CTS tests to configure temporary services if
|
||||
* mIsMultiple is true.
|
||||
* <p>Typically used by Shell command and/or CTS tests.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<String[]> mTemporaryServiceNamesList = new SparseArray<>();
|
||||
private final SparseArray<String> mTemporaryServiceNames = new SparseArray<>();
|
||||
|
||||
/**
|
||||
* Map of default services that have been disabled by
|
||||
* {@link #setDefaultServiceEnabled(int, boolean)},keyed by {@code userId}.
|
||||
@@ -71,7 +69,7 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private final SparseBooleanArray mDefaultServicesDisabled = new SparseBooleanArray();
|
||||
@Nullable private NameResolverListener mOnSetCallback;
|
||||
|
||||
/**
|
||||
* When the temporary service will expire (and reset back to the default).
|
||||
*/
|
||||
@@ -87,22 +85,7 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
public FrameworkResourcesServiceNameResolver(@NonNull Context context,
|
||||
@StringRes int resourceId) {
|
||||
mContext = context;
|
||||
mStringResourceId = resourceId;
|
||||
mArrayResourceId = -1;
|
||||
mIsMultiple = false;
|
||||
}
|
||||
|
||||
public FrameworkResourcesServiceNameResolver(@NonNull Context context,
|
||||
@ArrayRes int resourceId, boolean 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;
|
||||
mResourceId = resourceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -112,32 +95,23 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
}
|
||||
}
|
||||
|
||||
@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];
|
||||
synchronized (mLock) {
|
||||
final String name = mContext.getString(mResourceId);
|
||||
return TextUtils.isEmpty(name) ? null : name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default list of the service names for the given user.
|
||||
*
|
||||
* <p>Typically implemented by services which want to provide multiple backends.
|
||||
*/
|
||||
@Override
|
||||
public String[] getServiceNameList(int userId) {
|
||||
public String getServiceName(@UserIdInt int userId) {
|
||||
synchronized (mLock) {
|
||||
String[] temporaryNames = mTemporaryServiceNamesList.get(userId);
|
||||
if (temporaryNames != null) {
|
||||
final String temporaryName = mTemporaryServiceNames.get(userId);
|
||||
if (temporaryName != 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;
|
||||
Slog.w(TAG, "getServiceName(): using temporary name " + temporaryName
|
||||
+ " for user " + userId);
|
||||
return temporaryName;
|
||||
}
|
||||
final boolean disabled = mDefaultServicesDisabled.get(userId);
|
||||
if (disabled) {
|
||||
@@ -146,50 +120,22 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
+ "user " + userId);
|
||||
return null;
|
||||
}
|
||||
return getDefaultServiceNameList(userId);
|
||||
|
||||
return getDefaultServiceName(userId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default list of the service names for the given user.
|
||||
*
|
||||
* <p>Typically implemented by services which want to provide multiple backends.
|
||||
*/
|
||||
@Override
|
||||
public String[] getDefaultServiceNameList(int userId) {
|
||||
synchronized (mLock) {
|
||||
if (mIsMultiple) {
|
||||
return mContext.getResources().getStringArray(mArrayResourceId);
|
||||
} 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;
|
||||
return mTemporaryServiceNames.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);
|
||||
mTemporaryServiceNames.put(userId, componentName);
|
||||
|
||||
if (mTemporaryHandler == null) {
|
||||
mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) {
|
||||
@@ -209,10 +155,8 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
}
|
||||
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);
|
||||
}
|
||||
notifyTemporaryServiceNameChangedLocked(userId, componentName,
|
||||
/* isTemporary= */ true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,8 +164,8 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
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);
|
||||
+ mTemporaryServiceNames.get(userId));
|
||||
mTemporaryServiceNames.remove(userId);
|
||||
if (mTemporaryHandler != null) {
|
||||
mTemporaryHandler.removeMessages(MSG_RESET_TEMPORARY_SERVICE);
|
||||
mTemporaryHandler = null;
|
||||
@@ -263,21 +207,16 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
synchronized (mLock) {
|
||||
return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNamesList + "]";
|
||||
}
|
||||
return "FrameworkResourcesServiceNamer[temps=" + mTemporaryServiceNames + "]";
|
||||
}
|
||||
|
||||
// TODO(b/117779333): support proto
|
||||
@Override
|
||||
public void dumpShort(@NonNull PrintWriter pw) {
|
||||
synchronized (mLock) {
|
||||
pw.print("FrameworkResourcesServiceNamer: resId=");
|
||||
pw.print(mStringResourceId);
|
||||
pw.print(", numberTemps=");
|
||||
pw.print(mTemporaryServiceNamesList.size());
|
||||
pw.print(", enabledDefaults=");
|
||||
pw.print(mDefaultServicesDisabled.size());
|
||||
pw.print("FrameworkResourcesServiceNamer: resId="); pw.print(mResourceId);
|
||||
pw.print(", numberTemps="); pw.print(mTemporaryServiceNames.size());
|
||||
pw.print(", enabledDefaults="); pw.print(mDefaultServicesDisabled.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,17 +224,13 @@ public final class FrameworkResourcesServiceNameResolver implements ServiceNameR
|
||||
@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 String temporaryName = mTemporaryServiceNames.get(userId);
|
||||
if (temporaryName != null) {
|
||||
pw.print("tmpName="); pw.print(temporaryName);
|
||||
final long ttl = mTemporaryServiceExpiration - SystemClock.elapsedRealtime();
|
||||
pw.print(" (expires in ");
|
||||
TimeUtils.formatDuration(ttl, pw);
|
||||
pw.print("), ");
|
||||
pw.print(" (expires in "); TimeUtils.formatDuration(ttl, pw); pw.print("), ");
|
||||
}
|
||||
pw.print("defaultName=");
|
||||
pw.print(getDefaultServiceName(userId));
|
||||
pw.print("defaultName="); pw.print(getDefaultServiceName(userId));
|
||||
final boolean disabled = mDefaultServicesDisabled.get(userId);
|
||||
pw.println(disabled ? " (disabled)" : " (enabled)");
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public interface ServiceNameResolver {
|
||||
/**
|
||||
* Listener for name changes.
|
||||
*/
|
||||
interface NameResolverListener {
|
||||
public interface NameResolverListener {
|
||||
|
||||
/**
|
||||
* The name change callback.
|
||||
@@ -63,30 +63,6 @@ public interface ServiceNameResolver {
|
||||
@Nullable
|
||||
String getDefaultServiceName(@UserIdInt int userId);
|
||||
|
||||
/**
|
||||
* Gets the default list of names of the services for the given user.
|
||||
*
|
||||
* <p>Typically implemented by reading a Settings property or framework resource.
|
||||
*/
|
||||
@Nullable
|
||||
default String[] getDefaultServiceNameList(@UserIdInt int userId) {
|
||||
if (isConfiguredInMultipleMode()) {
|
||||
throw new UnsupportedOperationException("getting default service list not supported");
|
||||
} else {
|
||||
return new String[] { getDefaultServiceName(userId) };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the resolver is configured to connect to multiple backend services.
|
||||
* The default return type is false.
|
||||
*
|
||||
* <p>Typically implemented by reading a Settings property or framework resource.
|
||||
*/
|
||||
default boolean isConfiguredInMultipleMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current name of the service for the given user
|
||||
*
|
||||
@@ -99,18 +75,6 @@ public interface ServiceNameResolver {
|
||||
return getDefaultServiceName(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current name of the service for the given user
|
||||
*
|
||||
* @return either the temporary name (set by
|
||||
* {@link #setTemporaryService(int, String, int)}, or the
|
||||
* {@link #getDefaultServiceName(int) default name}.
|
||||
*/
|
||||
@Nullable
|
||||
default String[] getServiceNameList(@UserIdInt int userId) {
|
||||
return getDefaultServiceNameList(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the current service is temporary for the given user.
|
||||
*/
|
||||
@@ -121,11 +85,11 @@ public interface ServiceNameResolver {
|
||||
/**
|
||||
* Temporarily sets the service implementation for the given user.
|
||||
*
|
||||
* @param userId user handle
|
||||
* @param userId user handle
|
||||
* @param componentName name of the new component
|
||||
* @param durationMs how long the change will be valid (the service will be automatically
|
||||
* reset
|
||||
* to the default component after this timeout expires).
|
||||
* @param durationMs how long the change will be valid (the service will be automatically reset
|
||||
* to the default component after this timeout expires).
|
||||
*
|
||||
* @throws UnsupportedOperationException if not implemented.
|
||||
*/
|
||||
default void setTemporaryService(@UserIdInt int userId, @NonNull String componentName,
|
||||
@@ -133,25 +97,11 @@ public interface ServiceNameResolver {
|
||||
throw new UnsupportedOperationException("temporary user not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily sets the service implementation for the given user.
|
||||
*
|
||||
* @param userId user handle
|
||||
* @param componentNames list of the names of the new component
|
||||
* @param durationMs how long the change will be valid (the service will be automatically
|
||||
* reset
|
||||
* to the default component after this timeout expires).
|
||||
* @throws UnsupportedOperationException if not implemented.
|
||||
*/
|
||||
default void setTemporaryServices(@UserIdInt int userId, @NonNull String[] componentNames,
|
||||
int durationMs) {
|
||||
throw new UnsupportedOperationException("temporary user not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the temporary service implementation to the default component for the given user.
|
||||
*
|
||||
* @param userId user handle
|
||||
*
|
||||
* @throws UnsupportedOperationException if not implemented.
|
||||
*/
|
||||
default void resetTemporaryService(@UserIdInt int userId) {
|
||||
@@ -164,11 +114,11 @@ public interface ServiceNameResolver {
|
||||
* <p>Typically used during CTS tests to make sure only the default service doesn't interfere
|
||||
* with the test results.
|
||||
*
|
||||
* @param userId user handle
|
||||
* @param userId user handle
|
||||
* @param enabled whether the default service should be used when the temporary service is not
|
||||
* set. If the service enabled state is already that value, the command is
|
||||
* ignored and this
|
||||
* method return {@code false}.
|
||||
* set. If the service enabled state is already that value, the command is ignored and this
|
||||
* method return {@code false}.
|
||||
*
|
||||
* @return whether the enabled state changed.
|
||||
* @throws UnsupportedOperationException if not implemented.
|
||||
*/
|
||||
@@ -183,6 +133,7 @@ public interface ServiceNameResolver {
|
||||
* with the test results.
|
||||
*
|
||||
* @param userId user handle
|
||||
*
|
||||
* @throws UnsupportedOperationException if not implemented.
|
||||
*/
|
||||
default boolean isDefaultServiceEnabled(@UserIdInt int userId) {
|
||||
|
||||
Reference in New Issue
Block a user