Merge "Use the migrated injected setting code in settingslib. Manual merge to master from pi-car-dev Bug: 68198078 Test: Tested on device Change-Id: Iff767cd6bf7408b45ce9594628d3fd0a71744e9f"
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 55ec159..9d5f96f 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -389,9 +389,7 @@
*/
public static UserHandle getManagedProfile(UserManager userManager) {
List<UserHandle> userProfiles = userManager.getUserProfiles();
- final int count = userProfiles.size();
- for (int i = 0; i < count; i++) {
- final UserHandle profile = userProfiles.get(i);
+ for (UserHandle profile : userProfiles) {
if (profile.getIdentifier() == userManager.getUserHandle()) {
continue;
}
diff --git a/src/com/android/settings/location/InjectedSetting.java b/src/com/android/settings/location/InjectedSetting.java
deleted file mode 100644
index 4877cb4..0000000
--- a/src/com/android/settings/location/InjectedSetting.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2013 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.settings.location;
-
-import android.content.Intent;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.internal.annotations.Immutable;
-
-import java.util.Objects;
-
-/**
- * Specifies a setting that is being injected into Settings > Location > Location services.
- *
- * @see android.location.SettingInjectorService
- */
-@Immutable
-class InjectedSetting {
-
- /**
- * Package for the subclass of {@link android.location.SettingInjectorService} and for the
- * settings activity.
- */
- public final String packageName;
-
- /**
- * Class name for the subclass of {@link android.location.SettingInjectorService} that
- * specifies dynamic values for the location setting.
- */
- public final String className;
-
- /**
- * The {@link androidx.preference.Preference#getTitle()} value.
- */
- public final String title;
-
- /**
- * The {@link androidx.preference.Preference#getIcon()} value.
- */
- public final int iconId;
-
- /**
- * The user/profile associated with this setting (e.g. managed profile)
- */
- public final UserHandle mUserHandle;
-
- /**
- * The activity to launch to allow the user to modify the settings value. Assumed to be in the
- * {@link #packageName} package.
- */
- public final String settingsActivity;
-
- /**
- * The user restriction associated with this setting.
- */
- public final String userRestriction;
-
- private InjectedSetting(Builder builder) {
- this.packageName = builder.mPackageName;
- this.className = builder.mClassName;
- this.title = builder.mTitle;
- this.iconId = builder.mIconId;
- this.mUserHandle = builder.mUserHandle;
- this.settingsActivity = builder.mSettingsActivity;
- this.userRestriction = builder.mUserRestriction;
- }
-
- @Override
- public String toString() {
- return "InjectedSetting{" +
- "mPackageName='" + packageName + '\'' +
- ", mClassName='" + className + '\'' +
- ", label=" + title +
- ", iconId=" + iconId +
- ", userId=" + mUserHandle.getIdentifier() +
- ", settingsActivity='" + settingsActivity + '\'' +
- ", userRestriction='" + userRestriction +
- '}';
- }
-
- /**
- * Returns the intent to start the {@link #className} service.
- */
- public Intent getServiceIntent() {
- Intent intent = new Intent();
- intent.setClassName(packageName, className);
- return intent;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof InjectedSetting)) return false;
-
- InjectedSetting that = (InjectedSetting) o;
-
- return Objects.equals(packageName, that.packageName)
- && Objects.equals(className, that.className)
- && Objects.equals(title, that.title)
- && Objects.equals(iconId, that.iconId)
- && Objects.equals(mUserHandle, that.mUserHandle)
- && Objects.equals(settingsActivity, that.settingsActivity)
- && Objects.equals(userRestriction, that.userRestriction);
- }
-
- @Override
- public int hashCode() {
- int result = packageName.hashCode();
- result = 31 * result + className.hashCode();
- result = 31 * result + title.hashCode();
- result = 31 * result + iconId;
- result = 31 * result + (mUserHandle == null ? 0 : mUserHandle.hashCode());
- result = 31 * result + settingsActivity.hashCode();
- result = 31 * result + (userRestriction == null ? 0 : userRestriction.hashCode());
- return result;
- }
-
- public static class Builder {
- private String mPackageName;
- private String mClassName;
- private String mTitle;
- private int mIconId;
- private UserHandle mUserHandle;
- private String mSettingsActivity;
- private String mUserRestriction;
-
- public Builder setPackageName(String packageName) {
- mPackageName = packageName;
- return this;
- }
-
- public Builder setClassName(String className) {
- mClassName = className;
- return this;
- }
-
- public Builder setTitle(String title) {
- mTitle = title;
- return this;
- }
-
- public Builder setIconId(int iconId) {
- mIconId = iconId;
- return this;
- }
-
- public Builder setUserHandle(UserHandle userHandle) {
- mUserHandle = userHandle;
- return this;
- }
-
- public Builder setSettingsActivity(String settingsActivity) {
- mSettingsActivity = settingsActivity;
- return this;
- }
-
- public Builder setUserRestriction(String userRestriction) {
- mUserRestriction = userRestriction;
- return this;
- }
-
- public InjectedSetting build() {
- if (mPackageName == null || mClassName == null || TextUtils.isEmpty(mTitle)
- || TextUtils.isEmpty(mSettingsActivity)) {
- if (Log.isLoggable(SettingsInjector.TAG, Log.WARN)) {
- Log.w(SettingsInjector.TAG, "Illegal setting specification: package="
- + mPackageName + ", class=" + mClassName
- + ", title=" + mTitle + ", settingsActivity=" + mSettingsActivity);
- }
- return null;
- }
- return new InjectedSetting(this);
- }
- }
-}
diff --git a/src/com/android/settings/location/SettingsInjector.java b/src/com/android/settings/location/SettingsInjector.java
index 1206e85..4137933 100644
--- a/src/com/android/settings/location/SettingsInjector.java
+++ b/src/com/android/settings/location/SettingsInjector.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -16,228 +16,67 @@
package com.android.settings.location;
-import android.app.ActivityManager;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
-import android.location.SettingInjectorService;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
-import android.util.AttributeSet;
import android.util.IconDrawableFactory;
import android.util.Log;
-import android.util.Xml;
import com.android.settings.widget.AppPreference;
import com.android.settings.widget.RestrictedAppPreference;
+import com.android.settingslib.location.BaseSettingsInjector;
+import com.android.settingslib.location.InjectedSetting;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import androidx.preference.Preference;
/**
* Adds the preferences specified by the {@link InjectedSetting} objects to a preference group.
- *
- * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}. We do not use that
- * class directly because it is not a good match for our use case: we do not need the caching, and
- * so do not want the additional resource hit at app install/upgrade time; and we would have to
- * suppress the tie-breaking between multiple services reporting settings with the same name.
- * Code-sharing would require extracting {@link
- * android.content.pm.RegisteredServicesCache#parseServiceAttributes(android.content.res.Resources,
- * String, android.util.AttributeSet)} into an interface, which didn't seem worth it.
*/
-class SettingsInjector {
+public class SettingsInjector extends BaseSettingsInjector {
static final String TAG = "SettingsInjector";
- /**
- * If reading the status of a setting takes longer than this, we go ahead and start reading
- * the next setting.
- */
- private static final long INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS = 1000;
-
- /**
- * {@link Message#what} value for starting to load status values
- * in case we aren't already in the process of loading them.
- */
- private static final int WHAT_RELOAD = 1;
-
- /**
- * {@link Message#what} value sent after receiving a status message.
- */
- private static final int WHAT_RECEIVED_STATUS = 2;
-
- /**
- * {@link Message#what} value sent after the timeout waiting for a status message.
- */
- private static final int WHAT_TIMEOUT = 3;
-
- private final Context mContext;
-
- /**
- * The settings that were injected
- */
- private final Set<Setting> mSettings;
-
- private final Handler mHandler;
+ Context mContext;
public SettingsInjector(Context context) {
+ super(context);
mContext = context;
- mSettings = new HashSet<Setting>();
- mHandler = new StatusLoadingHandler();
}
/**
- * Returns a list for a profile with one {@link InjectedSetting} object for each
- * {@link android.app.Service} that responds to
- * {@link SettingInjectorService#ACTION_SERVICE_INTENT} and provides the expected setting
- * metadata.
- *
- * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
- *
- * TODO: unit test
+ * Adds an injected setting to the root.
*/
- private List<InjectedSetting> getSettings(final UserHandle userHandle) {
- PackageManager pm = mContext.getPackageManager();
- Intent intent = new Intent(SettingInjectorService.ACTION_SERVICE_INTENT);
-
- final int profileId = userHandle.getIdentifier();
- List<ResolveInfo> resolveInfos =
- pm.queryIntentServicesAsUser(intent, PackageManager.GET_META_DATA, profileId);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Found services for profile id " + profileId + ": " + resolveInfos);
- }
- List<InjectedSetting> settings = new ArrayList<InjectedSetting>(resolveInfos.size());
- for (ResolveInfo resolveInfo : resolveInfos) {
- try {
- InjectedSetting setting = parseServiceInfo(resolveInfo, userHandle, pm);
- if (setting == null) {
- Log.w(TAG, "Unable to load service info " + resolveInfo);
- } else {
- settings.add(setting);
- }
- } catch (XmlPullParserException e) {
- Log.w(TAG, "Unable to load service info " + resolveInfo, e);
- } catch (IOException e) {
- Log.w(TAG, "Unable to load service info " + resolveInfo, e);
- }
- }
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "Loaded settings for profile id " + profileId + ": " + settings);
- }
-
- return settings;
- }
-
- /**
- * Returns the settings parsed from the attributes of the
- * {@link SettingInjectorService#META_DATA_NAME} tag, or null.
- *
- * Duplicates some code from {@link android.content.pm.RegisteredServicesCache}.
- */
- private static InjectedSetting parseServiceInfo(ResolveInfo service, UserHandle userHandle,
- PackageManager pm) throws XmlPullParserException, IOException {
-
- ServiceInfo si = service.serviceInfo;
- ApplicationInfo ai = si.applicationInfo;
-
- if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- if (Log.isLoggable(TAG, Log.WARN)) {
- Log.w(TAG, "Ignoring attempt to inject setting from app not in system image: "
- + service);
- return null;
- }
- }
-
- XmlResourceParser parser = null;
+ private Preference addServiceSetting(Context prefContext, List<Preference> prefs,
+ InjectedSetting info) {
+ final PackageManager pm = mContext.getPackageManager();
+ Drawable appIcon = null;
try {
- parser = si.loadXmlMetaData(pm, SettingInjectorService.META_DATA_NAME);
- if (parser == null) {
- throw new XmlPullParserException("No " + SettingInjectorService.META_DATA_NAME
- + " meta-data for " + service + ": " + si);
- }
-
- AttributeSet attrs = Xml.asAttributeSet(parser);
-
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
-
- String nodeName = parser.getName();
- if (!SettingInjectorService.ATTRIBUTES_NAME.equals(nodeName)) {
- throw new XmlPullParserException("Meta-data does not start with "
- + SettingInjectorService.ATTRIBUTES_NAME + " tag");
- }
-
- Resources res = pm.getResourcesForApplicationAsUser(si.packageName,
- userHandle.getIdentifier());
- return parseAttributes(si.packageName, si.name, userHandle, res, attrs);
+ final PackageItemInfo itemInfo = new PackageItemInfo();
+ itemInfo.icon = info.iconId;
+ itemInfo.packageName = info.packageName;
+ final ApplicationInfo appInfo = pm.getApplicationInfo(info.packageName,
+ PackageManager.GET_META_DATA);
+ appIcon = IconDrawableFactory.newInstance(mContext)
+ .getBadgedIcon(itemInfo, appInfo, info.mUserHandle.getIdentifier());
} catch (PackageManager.NameNotFoundException e) {
- throw new XmlPullParserException(
- "Unable to load resources for package " + si.packageName);
- } finally {
- if (parser != null) {
- parser.close();
- }
+ Log.e(TAG, "Can't get ApplicationInfo for " + info.packageName, e);
}
- }
-
- /**
- * Returns an immutable representation of the static attributes for the setting, or null.
- */
- private static InjectedSetting parseAttributes(String packageName, String className,
- UserHandle userHandle, Resources res, AttributeSet attrs) {
-
- TypedArray sa = res.obtainAttributes(attrs, android.R.styleable.SettingInjectorService);
- try {
- // Note that to help guard against malicious string injection, we do not allow dynamic
- // specification of the label (setting title)
- final String title = sa.getString(android.R.styleable.SettingInjectorService_title);
- final int iconId =
- sa.getResourceId(android.R.styleable.SettingInjectorService_icon, 0);
- final String settingsActivity =
- sa.getString(android.R.styleable.SettingInjectorService_settingsActivity);
- final String userRestriction = sa.getString(
- android.R.styleable.SettingInjectorService_userRestriction);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "parsed title: " + title + ", iconId: " + iconId
- + ", settingsActivity: " + settingsActivity);
- }
- return new InjectedSetting.Builder()
- .setPackageName(packageName)
- .setClassName(className)
- .setTitle(title)
- .setIconId(iconId)
- .setUserHandle(userHandle)
- .setSettingsActivity(settingsActivity)
- .setUserRestriction(userRestriction)
- .build();
- } finally {
- sa.recycle();
- }
+ Preference pref = TextUtils.isEmpty(info.userRestriction)
+ ? new AppPreference(prefContext)
+ : new RestrictedAppPreference(prefContext, info.userRestriction);
+ pref.setTitle(info.title);
+ pref.setSummary(null);
+ pref.setIcon(appIcon);
+ pref.setOnPreferenceClickListener(new ServiceSettingClickedListener(info));
+ prefs.add(pref);
+ return pref;
}
/**
@@ -266,312 +105,4 @@
return prefs;
}
-
- /**
- * Checks wheteher there is any preference that other apps have injected.
- *
- * @param profileId Identifier of the user/profile to obtain the injected settings for or
- * UserHandle.USER_CURRENT for all profiles associated with current user.
- */
- public boolean hasInjectedSettings(final int profileId) {
- final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
- final List<UserHandle> profiles = um.getUserProfiles();
- final int profileCount = profiles.size();
- for (int i = 0; i < profileCount; ++i) {
- final UserHandle userHandle = profiles.get(i);
- if (profileId == UserHandle.USER_CURRENT || profileId == userHandle.getIdentifier()) {
- Iterable<InjectedSetting> settings = getSettings(userHandle);
- for (InjectedSetting setting : settings) {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Reloads the status messages for all the preference items.
- */
- public void reloadStatusMessages() {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "reloadingStatusMessages: " + mSettings);
- }
- mHandler.sendMessage(mHandler.obtainMessage(WHAT_RELOAD));
- }
-
- /**
- * Adds an injected setting to the root.
- */
- private Preference addServiceSetting(Context prefContext, List<Preference> prefs,
- InjectedSetting info) {
- final PackageManager pm = mContext.getPackageManager();
- Drawable appIcon = null;
- try {
- final PackageItemInfo itemInfo = new PackageItemInfo();
- itemInfo.icon = info.iconId;
- itemInfo.packageName = info.packageName;
- final ApplicationInfo appInfo = pm.getApplicationInfo(info.packageName,
- PackageManager.GET_META_DATA);
- appIcon = IconDrawableFactory.newInstance(mContext)
- .getBadgedIcon(itemInfo, appInfo, info.mUserHandle.getIdentifier());
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Can't get ApplicationInfo for " + info.packageName, e);
- }
- Preference pref = TextUtils.isEmpty(info.userRestriction)
- ? new AppPreference(prefContext)
- : new RestrictedAppPreference(prefContext, info.userRestriction);
- pref.setTitle(info.title);
- pref.setSummary(null);
- pref.setIcon(appIcon);
- pref.setOnPreferenceClickListener(new ServiceSettingClickedListener(info));
- prefs.add(pref);
- return pref;
- }
-
- private class ServiceSettingClickedListener
- implements Preference.OnPreferenceClickListener {
- private InjectedSetting mInfo;
-
- public ServiceSettingClickedListener(InjectedSetting info) {
- mInfo = info;
- }
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- // Activity to start if they click on the preference. Must start in new task to ensure
- // that "android.settings.LOCATION_SOURCE_SETTINGS" brings user back to
- // Settings > Location.
- Intent settingIntent = new Intent();
- settingIntent.setClassName(mInfo.packageName, mInfo.settingsActivity);
- // Sometimes the user may navigate back to "Settings" and launch another different
- // injected setting after one injected setting has been launched.
- //
- // FLAG_ACTIVITY_CLEAR_TOP allows multiple Activities to stack on each other. When
- // "back" button is clicked, the user will navigate through all the injected settings
- // launched before. Such behavior could be quite confusing sometimes.
- //
- // In order to avoid such confusion, we use FLAG_ACTIVITY_CLEAR_TASK, which always clear
- // up all existing injected settings and make sure that "back" button always brings the
- // user back to "Settings" directly.
- settingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- mContext.startActivityAsUser(settingIntent, mInfo.mUserHandle);
- return true;
- }
- }
-
- /**
- * Loads the setting status values one at a time. Each load starts a subclass of {@link
- * SettingInjectorService}, so to reduce memory pressure we don't want to load too many at
- * once.
- */
- private final class StatusLoadingHandler extends Handler {
-
- /**
- * Settings whose status values need to be loaded. A set is used to prevent redundant loads.
- */
- private Set<Setting> mSettingsToLoad = new HashSet<Setting>();
-
- /**
- * Settings that are being loaded now and haven't timed out. In practice this should have
- * zero or one elements.
- */
- private Set<Setting> mSettingsBeingLoaded = new HashSet<Setting>();
-
- /**
- * Settings that are being loaded but have timed out. If only one setting has timed out, we
- * will go ahead and start loading the next setting so that one slow load won't delay the
- * load of the other settings.
- */
- private Set<Setting> mTimedOutSettings = new HashSet<Setting>();
-
- private boolean mReloadRequested;
-
- private StatusLoadingHandler() {
- super(Looper.getMainLooper());
- }
- @Override
- public void handleMessage(Message msg) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "handleMessage start: " + msg + ", " + this);
- }
-
- // Update state in response to message
- switch (msg.what) {
- case WHAT_RELOAD:
- mReloadRequested = true;
- break;
- case WHAT_RECEIVED_STATUS:
- final Setting receivedSetting = (Setting) msg.obj;
- receivedSetting.maybeLogElapsedTime();
- mSettingsBeingLoaded.remove(receivedSetting);
- mTimedOutSettings.remove(receivedSetting);
- removeMessages(WHAT_TIMEOUT, receivedSetting);
- break;
- case WHAT_TIMEOUT:
- final Setting timedOutSetting = (Setting) msg.obj;
- mSettingsBeingLoaded.remove(timedOutSetting);
- mTimedOutSettings.add(timedOutSetting);
- if (Log.isLoggable(TAG, Log.WARN)) {
- Log.w(TAG, "Timed out after " + timedOutSetting.getElapsedTime()
- + " millis trying to get status for: " + timedOutSetting);
- }
- break;
- default:
- Log.wtf(TAG, "Unexpected what: " + msg);
- }
-
- // Decide whether to load additional settings based on the new state. Start by seeing
- // if we have headroom to load another setting.
- if (mSettingsBeingLoaded.size() > 0 || mTimedOutSettings.size() > 1) {
- // Don't load any more settings until one of the pending settings has completed.
- // To reduce memory pressure, we want to be loading at most one setting (plus at
- // most one timed-out setting) at a time. This means we'll be responsible for
- // bringing in at most two services.
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "too many services already live for " + msg + ", " + this);
- }
- return;
- }
-
- if (mReloadRequested && mSettingsToLoad.isEmpty() && mSettingsBeingLoaded.isEmpty()
- && mTimedOutSettings.isEmpty()) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "reloading because idle and reload requesteed " + msg + ", " + this);
- }
- // Reload requested, so must reload all settings
- mSettingsToLoad.addAll(mSettings);
- mReloadRequested = false;
- }
-
- // Remove the next setting to load from the queue, if any
- Iterator<Setting> iter = mSettingsToLoad.iterator();
- if (!iter.hasNext()) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "nothing left to do for " + msg + ", " + this);
- }
- return;
- }
- Setting setting = iter.next();
- iter.remove();
-
- // Request the status value
- setting.startService();
- mSettingsBeingLoaded.add(setting);
-
- // Ensure that if receiving the status value takes too long, we start loading the
- // next value anyway
- Message timeoutMsg = obtainMessage(WHAT_TIMEOUT, setting);
- sendMessageDelayed(timeoutMsg, INJECTED_STATUS_UPDATE_TIMEOUT_MILLIS);
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "handleMessage end " + msg + ", " + this
- + ", started loading " + setting);
- }
- }
-
- @Override
- public String toString() {
- return "StatusLoadingHandler{" +
- "mSettingsToLoad=" + mSettingsToLoad +
- ", mSettingsBeingLoaded=" + mSettingsBeingLoaded +
- ", mTimedOutSettings=" + mTimedOutSettings +
- ", mReloadRequested=" + mReloadRequested +
- '}';
- }
- }
-
- /**
- * Represents an injected setting and the corresponding preference.
- */
- private final class Setting {
-
- public final InjectedSetting setting;
- public final Preference preference;
- public long startMillis;
-
- private Setting(InjectedSetting setting, Preference preference) {
- this.setting = setting;
- this.preference = preference;
- }
-
- @Override
- public String toString() {
- return "Setting{" +
- "setting=" + setting +
- ", preference=" + preference +
- '}';
- }
-
- /**
- * Returns true if they both have the same {@link #setting} value. Ignores mutable
- * {@link #preference} and {@link #startMillis} so that it's safe to use in sets.
- */
- @Override
- public boolean equals(Object o) {
- return this == o || o instanceof Setting && setting.equals(((Setting) o).setting);
- }
-
- @Override
- public int hashCode() {
- return setting.hashCode();
- }
-
- /**
- * Starts the service to fetch for the current status for the setting, and updates the
- * preference when the service replies.
- */
- public void startService() {
- final ActivityManager am = (ActivityManager)
- mContext.getSystemService(Context.ACTIVITY_SERVICE);
- if (!am.isUserRunning(setting.mUserHandle.getIdentifier())) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "Cannot start service as user "
- + setting.mUserHandle.getIdentifier() + " is not running");
- }
- return;
- }
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- Bundle bundle = msg.getData();
- boolean enabled = bundle.getBoolean(SettingInjectorService.ENABLED_KEY, true);
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, setting + ": received " + msg + ", bundle: " + bundle);
- }
- preference.setSummary(null);
- preference.setEnabled(enabled);
- mHandler.sendMessage(
- mHandler.obtainMessage(WHAT_RECEIVED_STATUS, Setting.this));
- }
- };
- Messenger messenger = new Messenger(handler);
-
- Intent intent = setting.getServiceIntent();
- intent.putExtra(SettingInjectorService.MESSENGER_KEY, messenger);
-
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, setting + ": sending update intent: " + intent
- + ", handler: " + handler);
- startMillis = SystemClock.elapsedRealtime();
- } else {
- startMillis = 0;
- }
-
- // Start the service, making sure that this is attributed to the user associated with
- // the setting rather than the system user.
- mContext.startServiceAsUser(intent, setting.mUserHandle);
- }
-
- public long getElapsedTime() {
- long end = SystemClock.elapsedRealtime();
- return end - startMillis;
- }
-
- public void maybeLogElapsedTime() {
- if (Log.isLoggable(TAG, Log.DEBUG) && startMillis != 0) {
- long elapsed = getElapsedTime();
- Log.d(TAG, this + " update took " + elapsed + " millis");
- }
- }
- }
}
diff --git a/tests/robotests/src/com/android/settings/location/InjectedSettingTest.java b/tests/robotests/src/com/android/settings/location/InjectedSettingTest.java
deleted file mode 100644
index 5045837..0000000
--- a/tests/robotests/src/com/android/settings/location/InjectedSettingTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.settings.location;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public final class InjectedSettingTest {
-
- private static final String TEST_STRING = "test";
-
- @Test
- public void buildWithoutPackageName_ShouldReturnNull() {
- assertThat(((new InjectedSetting.Builder())
- .setClassName(TEST_STRING)
- .setTitle(TEST_STRING)
- .setSettingsActivity(TEST_STRING).build())).isNull();
- }
-
- private InjectedSetting getTestSetting() {
- return new InjectedSetting.Builder()
- .setPackageName(TEST_STRING)
- .setClassName(TEST_STRING)
- .setTitle(TEST_STRING)
- .setSettingsActivity(TEST_STRING).build();
- }
-
- @Test
- public void testEquals() {
- InjectedSetting setting1 = getTestSetting();
- InjectedSetting setting2 = getTestSetting();
- assertThat(setting1).isEqualTo(setting2);
- }
-
- @Test
- public void testHashCode() {
- InjectedSetting setting = getTestSetting();
- assertThat(setting.hashCode()).isEqualTo(1225314048);
- }
-}