release-request-ed8626b9-4479-4c76-9207-5f511f136606-for-git_pi-release-4354758 snap-temp-L65900000105223161
Change-Id: I119935112476adee0e3843a076abb66626afd7d7
This commit is contained in:
@@ -15,7 +15,14 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:src="@drawable/ic_sim_sd"
|
||||
android:tint="?android:attr/colorControlNormal" />
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M19.99 4c0-1.1-.89-2-1.99-2h-8L4 8v12c0 1.1.9 2 2 2h12.01c1.1 0 1.99-.9 1.99-2l-.01-16zM9 19H7v-2h2v2zm8 0h-2v-2h2v2zm-8-4H7v-4h2v4zm4 4h-2v-4h2v4zm0-6h-2v-2h2v2zm4 2h-2v-4h2v4z"/>
|
||||
<path android:pathData="M0 0h24v24H0z"/>
|
||||
</vector>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
android:icon="@drawable/ic_lock"
|
||||
android:layout="@layout/suw_glif_blank_template"
|
||||
settings:suwFooter="@layout/choose_lock_pattern_common_footer"
|
||||
settings:suwHeaderText="@string/lockpassword_choose_your_pattern_header">
|
||||
settings:suwHeaderText="@string/lockpassword_choose_your_screen_lock_header">
|
||||
|
||||
<com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient
|
||||
android:id="@+id/topLayout"
|
||||
|
||||
@@ -217,7 +217,9 @@ public abstract class AppInfoBase extends SettingsPreferenceFragment
|
||||
|
||||
@Override
|
||||
public void onPackageListChanged() {
|
||||
refreshUi();
|
||||
if (!refreshUi()) {
|
||||
setIntentAndFinish(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startAppInfoFragment(Class<?> fragment, int titleRes,
|
||||
|
||||
@@ -22,14 +22,16 @@ import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageItemInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -37,9 +39,13 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.notification.EmptyTextSettings;
|
||||
import com.android.settings.wrapper.ActivityInfoWrapper;
|
||||
import com.android.settings.wrapper.UserManagerWrapper;
|
||||
import com.android.settingslib.wrapper.PackageManagerWrapper;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
@@ -51,8 +57,38 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
IGNORE_PACKAGE_LIST.add("com.android.systemui");
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator by name, then user id.
|
||||
* {@see PackageItemInfo#DisplayNameComparator}
|
||||
*/
|
||||
static class AppComparator implements Comparator<Pair<ApplicationInfo, Integer>> {
|
||||
|
||||
private final Collator mCollator = Collator.getInstance();
|
||||
private final PackageManager mPm;
|
||||
|
||||
public AppComparator(PackageManager pm) {
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
public final int compare(Pair<ApplicationInfo, Integer> a,
|
||||
Pair<ApplicationInfo, Integer> b) {
|
||||
CharSequence sa = a.first.loadLabel(mPm);
|
||||
if (sa == null) sa = a.first.name;
|
||||
CharSequence sb = b.first.loadLabel(mPm);
|
||||
if (sb == null) sb = b.first.name;
|
||||
int nameCmp = mCollator.compare(sa.toString(), sb.toString());
|
||||
if (nameCmp != 0) {
|
||||
return nameCmp;
|
||||
} else {
|
||||
return a.second - b.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private PackageManager mPackageManager;
|
||||
private PackageManagerWrapper mPackageManager;
|
||||
private UserManagerWrapper mUserManager;
|
||||
private IconDrawableFactory mIconDrawableFactory;
|
||||
|
||||
/**
|
||||
* @return true if the package has any activities that declare that they support
|
||||
@@ -94,12 +130,23 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
return false;
|
||||
}
|
||||
|
||||
public PictureInPictureSettings() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public PictureInPictureSettings(PackageManagerWrapper pm, UserManagerWrapper um) {
|
||||
mPackageManager = pm;
|
||||
mUserManager = um;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mContext = getActivity();
|
||||
mPackageManager = mContext.getPackageManager();
|
||||
mPackageManager = new PackageManagerWrapper(mContext.getPackageManager());
|
||||
mUserManager = new UserManagerWrapper(mContext.getSystemService(UserManager.class));
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
|
||||
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext));
|
||||
}
|
||||
|
||||
@@ -111,33 +158,25 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
screen.removeAll();
|
||||
|
||||
// Fetch the set of applications which have at least one activity that declare that they
|
||||
// support picture-in-picture
|
||||
final ArrayMap<String, Boolean> packageToState = new ArrayMap<>();
|
||||
final ArrayList<ApplicationInfo> pipApps = new ArrayList<>();
|
||||
final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, UserHandle.myUserId());
|
||||
for (PackageInfo packageInfo : installedPackages) {
|
||||
if (checkPackageHasPictureInPictureActivities(packageInfo.packageName,
|
||||
packageInfo.activities)) {
|
||||
final String packageName = packageInfo.applicationInfo.packageName;
|
||||
final boolean state = PictureInPictureDetails.getEnterPipStateForPackage(
|
||||
mContext, packageInfo.applicationInfo.uid, packageName);
|
||||
pipApps.add(packageInfo.applicationInfo);
|
||||
packageToState.put(packageName, state);
|
||||
}
|
||||
}
|
||||
Collections.sort(pipApps, new PackageItemInfo.DisplayNameComparator(mPackageManager));
|
||||
// Fetch the set of applications for each profile which have at least one activity that
|
||||
// declare that they support picture-in-picture
|
||||
final PackageManager pm = mPackageManager.getPackageManager();
|
||||
final ArrayList<Pair<ApplicationInfo, Integer>> pipApps =
|
||||
collectPipApps(UserHandle.myUserId());
|
||||
Collections.sort(pipApps, new AppComparator(pm));
|
||||
|
||||
// Rebuild the list of prefs
|
||||
final Context prefContext = getPrefContext();
|
||||
for (final ApplicationInfo appInfo : pipApps) {
|
||||
for (final Pair<ApplicationInfo, Integer> appData : pipApps) {
|
||||
final ApplicationInfo appInfo = appData.first;
|
||||
final int userId = appData.second;
|
||||
final UserHandle user = UserHandle.of(userId);
|
||||
final String packageName = appInfo.packageName;
|
||||
final CharSequence label = appInfo.loadLabel(mPackageManager);
|
||||
final CharSequence label = appInfo.loadLabel(pm);
|
||||
|
||||
final Preference pref = new Preference(prefContext);
|
||||
pref.setIcon(appInfo.loadIcon(mPackageManager));
|
||||
pref.setTitle(label);
|
||||
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appInfo, userId));
|
||||
pref.setTitle(pm.getUserBadgedLabel(label, user));
|
||||
pref.setSummary(PictureInPictureDetails.getPreferenceSummary(prefContext,
|
||||
appInfo.uid, packageName));
|
||||
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@@ -163,4 +202,28 @@ public class PictureInPictureSettings extends EmptyTextSettings {
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.SETTINGS_MANAGE_PICTURE_IN_PICTURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of applications for the given user and all their profiles that have
|
||||
* activities which support PiP.
|
||||
*/
|
||||
ArrayList<Pair<ApplicationInfo, Integer>> collectPipApps(int userId) {
|
||||
final ArrayList<Pair<ApplicationInfo, Integer>> pipApps = new ArrayList<>();
|
||||
final ArrayList<Integer> userIds = new ArrayList<>();
|
||||
for (UserInfo user : mUserManager.getProfiles(userId)) {
|
||||
userIds.add(user.id);
|
||||
}
|
||||
|
||||
for (int id : userIds) {
|
||||
final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
|
||||
GET_ACTIVITIES, id);
|
||||
for (PackageInfo packageInfo : installedPackages) {
|
||||
if (checkPackageHasPictureInPictureActivities(packageInfo.packageName,
|
||||
packageInfo.activities)) {
|
||||
pipApps.add(new Pair<>(packageInfo.applicationInfo, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pipApps;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,9 @@ public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenc
|
||||
|
||||
@Override
|
||||
protected boolean refreshUi() {
|
||||
if (mPackageInfo == null) {
|
||||
return false;
|
||||
}
|
||||
mUsageState = mUsageBridge.getUsageInfo(mPackageName,
|
||||
mPackageInfo.applicationInfo.uid);
|
||||
|
||||
|
||||
@@ -42,31 +42,21 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
private final LocalBluetoothManager mBluetoothManager;
|
||||
private final LocalBluetoothAdapter mBluetoothAdapter;
|
||||
|
||||
private boolean mEnabled;
|
||||
private int mConnectionState;
|
||||
|
||||
public BluetoothSummaryUpdater(Context context, OnSummaryChangeListener listener,
|
||||
LocalBluetoothManager bluetoothManager) {
|
||||
super(context, listener);
|
||||
mBluetoothManager = bluetoothManager;
|
||||
mBluetoothAdapter = mBluetoothManager != null
|
||||
? mBluetoothManager.getBluetoothAdapter() : null;
|
||||
? mBluetoothManager.getBluetoothAdapter() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChanged(int bluetoothState) {
|
||||
mEnabled = bluetoothState == BluetoothAdapter.STATE_ON
|
||||
|| bluetoothState == BluetoothAdapter.STATE_TURNING_ON;
|
||||
if (!mEnabled) {
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
}
|
||||
notifyChangeIfNeeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
|
||||
mConnectionState = state;
|
||||
updateConnected();
|
||||
notifyChangeIfNeeded();
|
||||
}
|
||||
|
||||
@@ -92,8 +82,6 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
return;
|
||||
}
|
||||
if (listening) {
|
||||
mEnabled = mBluetoothAdapter.isEnabled();
|
||||
mConnectionState = mBluetoothAdapter.getConnectionState();
|
||||
notifyChangeIfNeeded();
|
||||
mBluetoothManager.getEventManager().registerCallback(this);
|
||||
} else {
|
||||
@@ -103,10 +91,10 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
if (!mEnabled) {
|
||||
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
|
||||
return mContext.getString(R.string.bluetooth_disabled);
|
||||
}
|
||||
switch (mConnectionState) {
|
||||
switch (mBluetoothAdapter.getConnectionState()) {
|
||||
case BluetoothAdapter.STATE_CONNECTED:
|
||||
return getConnectedDeviceSummary();
|
||||
case BluetoothAdapter.STATE_CONNECTING:
|
||||
@@ -118,50 +106,17 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
}
|
||||
}
|
||||
|
||||
private void updateConnected() {
|
||||
if (mBluetoothAdapter == null) {
|
||||
return;
|
||||
}
|
||||
// Make sure our connection state is up to date.
|
||||
int state = mBluetoothAdapter.getConnectionState();
|
||||
if (state != mConnectionState) {
|
||||
mConnectionState = state;
|
||||
return;
|
||||
}
|
||||
final Collection<CachedBluetoothDevice> devices = getDevices();
|
||||
if (devices == null) {
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
if (mConnectionState == BluetoothAdapter.STATE_CONNECTED) {
|
||||
CachedBluetoothDevice connectedDevice = null;
|
||||
for (CachedBluetoothDevice device : devices) {
|
||||
if (device.isConnected()) {
|
||||
connectedDevice = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connectedDevice == null) {
|
||||
// If somehow we think we are connected, but have no connected devices, we
|
||||
// aren't connected.
|
||||
mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<CachedBluetoothDevice> getDevices() {
|
||||
return mBluetoothManager != null
|
||||
? mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy()
|
||||
: null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
String getConnectedDeviceSummary() {
|
||||
String deviceName = null;
|
||||
int count = 0;
|
||||
final Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
|
||||
if (devices == null || devices.isEmpty()) {
|
||||
return null;
|
||||
if (devices == null) {
|
||||
Log.e(TAG, "getConnectedDeviceSummary, bonded devices are null");
|
||||
return mContext.getString(R.string.bluetooth_disabled);
|
||||
} else if (devices.isEmpty()) {
|
||||
Log.e(TAG, "getConnectedDeviceSummary, no bonded devices");
|
||||
return mContext.getString(R.string.disconnected);
|
||||
}
|
||||
for (BluetoothDevice device : devices) {
|
||||
if (device.isConnected()) {
|
||||
@@ -173,12 +128,13 @@ public final class BluetoothSummaryUpdater extends SummaryUpdater implements Blu
|
||||
}
|
||||
}
|
||||
if (deviceName == null) {
|
||||
Log.w(TAG, "getConnectedDeviceSummary, deviceName is null, numBondedDevices="
|
||||
Log.e(TAG, "getConnectedDeviceSummary, deviceName is null, numBondedDevices="
|
||||
+ devices.size());
|
||||
for (BluetoothDevice device : devices) {
|
||||
Log.w(TAG, "getConnectedDeviceSummary, device=" + device.getName() + "["
|
||||
Log.e(TAG, "getConnectedDeviceSummary, device=" + device.getName() + "["
|
||||
+ device.getAddress() + "]" + ", isConnected=" + device.isConnected());
|
||||
}
|
||||
return mContext.getString(R.string.disconnected);
|
||||
}
|
||||
return count > 1 ? mContext.getString(R.string.bluetooth_connected_multiple_devices_summary)
|
||||
: mContext.getString(R.string.bluetooth_connected_summary, deviceName);
|
||||
|
||||
@@ -65,4 +65,8 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
|
||||
protected final Context getPrefContext() {
|
||||
return getPreferenceManager().getContext();
|
||||
}
|
||||
|
||||
protected final VisibilityLoggerMixin getVisibilityLogger() {
|
||||
return mVisibilityLoggerMixin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.settings.core.instrumentation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.metrics.LogMaker;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
@@ -28,6 +29,8 @@ import com.android.internal.logging.nano.MetricsProto;
|
||||
*/
|
||||
public class EventLogWriter implements LogWriter {
|
||||
|
||||
private final MetricsLogger mMetricsLogger = new MetricsLogger();
|
||||
|
||||
public void visible(Context context, int source, int category) {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_OPEN)
|
||||
@@ -39,6 +42,24 @@ public class EventLogWriter implements LogWriter {
|
||||
MetricsLogger.hidden(context, category);
|
||||
}
|
||||
|
||||
public void action(int category, int value, Pair<Integer, Object>... taggedData) {
|
||||
if (taggedData == null || taggedData.length == 0) {
|
||||
mMetricsLogger.action(category, value);
|
||||
} else {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(value);
|
||||
for (Pair<Integer, Object> pair : taggedData) {
|
||||
logMaker.addTaggedData(pair.first, pair.second);
|
||||
}
|
||||
mMetricsLogger.write(logMaker);
|
||||
}
|
||||
}
|
||||
|
||||
public void action(int category, boolean value, Pair<Integer, Object>... taggedData) {
|
||||
action(category, value ? 1 : 0, taggedData);
|
||||
}
|
||||
|
||||
public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
|
||||
action(context, category, "", taggedData);
|
||||
}
|
||||
@@ -52,12 +73,16 @@ public class EventLogWriter implements LogWriter {
|
||||
MetricsLogger.action(logMaker);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(int, int, Pair[])} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, int value) {
|
||||
MetricsLogger.action(context, category, Integer.toString(value));
|
||||
MetricsLogger.action(context, category, value);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(int, boolean, Pair[])} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, boolean value) {
|
||||
MetricsLogger.action(context, category, Boolean.toString(value));
|
||||
MetricsLogger.action(context, category, value);
|
||||
}
|
||||
|
||||
public void action(Context context, int category, String pkg,
|
||||
|
||||
@@ -33,6 +33,16 @@ public interface LogWriter {
|
||||
*/
|
||||
void hidden(Context context, int category);
|
||||
|
||||
/**
|
||||
* Logs a user action.
|
||||
*/
|
||||
void action(int category, int value, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs a user action.
|
||||
*/
|
||||
void action(int category, boolean value, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
*/
|
||||
@@ -45,12 +55,16 @@ public interface LogWriter {
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
* @deprecated use {@link #action(int, int, Pair[])}
|
||||
*/
|
||||
@Deprecated
|
||||
void action(Context context, int category, int value);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
* @deprecated use {@link #action(int, boolean, Pair[])}
|
||||
*/
|
||||
@Deprecated
|
||||
void action(Context context, int category, boolean value);
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -60,18 +60,44 @@ public class MetricsFeatureProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user action. Includes the elapsed time since the containing
|
||||
* fragment has been visible.
|
||||
*/
|
||||
public void action(VisibilityLoggerMixin visibilityLogger, int category, int value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(category, value,
|
||||
sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user action. Includes the elapsed time since the containing
|
||||
* fragment has been visible.
|
||||
*/
|
||||
public void action(VisibilityLoggerMixin visibilityLogger, int category, boolean value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(category, value,
|
||||
sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, taggedData);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(VisibilityLoggerMixin, int, int)} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, int value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, value);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(VisibilityLoggerMixin, int, boolean)} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, boolean value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, value);
|
||||
@@ -99,7 +125,7 @@ public class MetricsFeatureProvider {
|
||||
|
||||
public int getMetricsCategory(Object object) {
|
||||
if (object == null || !(object instanceof Instrumentable)) {
|
||||
return MetricsProto.MetricsEvent.VIEW_UNKNOWN;
|
||||
return MetricsEvent.VIEW_UNKNOWN;
|
||||
}
|
||||
return ((Instrumentable) object).getMetricsCategory();
|
||||
}
|
||||
@@ -116,15 +142,19 @@ public class MetricsFeatureProvider {
|
||||
// Not loggable
|
||||
return;
|
||||
}
|
||||
action(context, MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
|
||||
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
|
||||
Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
return;
|
||||
} else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
|
||||
// Going to a Setting internal page, skip click logging in favor of page's own
|
||||
// visibility logging.
|
||||
return;
|
||||
}
|
||||
action(context, MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
|
||||
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
|
||||
Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
}
|
||||
|
||||
private Pair<Integer, Object> sinceVisibleTaggedData(long timestamp) {
|
||||
return Pair.create(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,14 @@ public class SettingSuggestionsLogWriter implements LogWriter {
|
||||
public void actionWithSource(Context context, int source, int category) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(int category, int value, Pair<Integer, Object>... taggedData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(int category, boolean value, Pair<Integer, Object>... taggedData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void action(Context context, int category, int value) {
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
@@ -41,6 +42,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau
|
||||
|
||||
private MetricsFeatureProvider mMetricsFeature;
|
||||
private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
|
||||
private long mVisibleTimestamp;
|
||||
|
||||
public VisibilityLoggerMixin(int metricsCategory) {
|
||||
// MetricsFeature will be set during onAttach.
|
||||
@@ -59,6 +61,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mVisibleTimestamp = SystemClock.elapsedRealtime();
|
||||
if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
|
||||
mMetricsFeature.visible(null /* context */, mSourceMetricsCategory, mMetricsCategory);
|
||||
}
|
||||
@@ -66,6 +69,7 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mVisibleTimestamp = 0;
|
||||
if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
|
||||
mMetricsFeature.hidden(null /* context */, mMetricsCategory);
|
||||
}
|
||||
@@ -85,4 +89,12 @@ public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPau
|
||||
mSourceMetricsCategory = intent.getIntExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
MetricsProto.MetricsEvent.VIEW_UNKNOWN);
|
||||
}
|
||||
|
||||
/** Returns elapsed time since onResume() */
|
||||
public long elapsedTimeSinceVisible() {
|
||||
if (mVisibleTimestamp == 0) {
|
||||
return 0;
|
||||
}
|
||||
return SystemClock.elapsedRealtime() - mVisibleTimestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +220,9 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
|
||||
public Tile getSuggestion(int position) {
|
||||
final long itemId = getItemId(position);
|
||||
if (mSuggestions == null) {
|
||||
return null;
|
||||
}
|
||||
for (Tile tile : mSuggestions) {
|
||||
if (Objects.hash(tile.title) == itemId) {
|
||||
return tile;
|
||||
@@ -230,6 +233,9 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
|
||||
public Suggestion getSuggestionsV2(int position) {
|
||||
final long itemId = getItemId(position);
|
||||
if (mSuggestionsV2 == null) {
|
||||
return null;
|
||||
}
|
||||
for (Suggestion suggestion : mSuggestionsV2) {
|
||||
if (Objects.hash(suggestion.getId()) == itemId) {
|
||||
return suggestion;
|
||||
|
||||
@@ -194,8 +194,7 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
|
||||
@VisibleForTesting
|
||||
boolean hasUsedNightDisplay(Context context) {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final long lastActivatedTimeMillis = Secure.getLong(cr,
|
||||
Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1);
|
||||
return lastActivatedTimeMillis > 0;
|
||||
return Secure.getInt(cr, Secure.NIGHT_DISPLAY_AUTO_MODE, 0) != 0
|
||||
|| Secure.getString(cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME) != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,12 +69,12 @@ public class BluetoothSnoopLogPreferenceController extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeveloperOptionsEnabled() {
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeveloperOptionsDisabled() {
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
SystemProperties.set(BLUETOOTH_BTSNOOP_ENABLE_PROPERTY, Boolean.toString(false));
|
||||
mPreference.setChecked(false);
|
||||
mPreference.setEnabled(false);
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.view.Display;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ColorModePreference extends SwitchPreference implements DisplayListener {
|
||||
|
||||
@@ -35,7 +36,28 @@ public class ColorModePreference extends SwitchPreference implements DisplayList
|
||||
private Display mDisplay;
|
||||
|
||||
private int mCurrentIndex;
|
||||
private ArrayList<ColorModeDescription> mDescriptions;
|
||||
private List<ColorModeDescription> mDescriptions;
|
||||
|
||||
public static List<ColorModeDescription> getColorModeDescriptions(Context context) {
|
||||
|
||||
List<ColorModeDescription> colorModeDescriptions = new ArrayList<>();
|
||||
Resources resources = context.getResources();
|
||||
int[] colorModes = resources.getIntArray(R.array.color_mode_ids);
|
||||
String[] titles = resources.getStringArray(R.array.color_mode_names);
|
||||
String[] descriptions = resources.getStringArray(R.array.color_mode_descriptions);
|
||||
// Map the resource information describing color modes.
|
||||
for (int i = 0; i < colorModes.length; i++) {
|
||||
if (colorModes[i] != -1 && i != 1 /* Skip Natural for now. */) {
|
||||
ColorModeDescription desc = new ColorModeDescription();
|
||||
desc.colorMode = colorModes[i];
|
||||
desc.title = titles[i];
|
||||
desc.summary = descriptions[i];
|
||||
colorModeDescriptions.add(desc);
|
||||
}
|
||||
}
|
||||
|
||||
return colorModeDescriptions;
|
||||
}
|
||||
|
||||
public ColorModePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -75,22 +97,7 @@ public class ColorModePreference extends SwitchPreference implements DisplayList
|
||||
public void updateCurrentAndSupported() {
|
||||
mDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
|
||||
|
||||
mDescriptions = new ArrayList<>();
|
||||
|
||||
Resources resources = getContext().getResources();
|
||||
int[] colorModes = resources.getIntArray(R.array.color_mode_ids);
|
||||
String[] titles = resources.getStringArray(R.array.color_mode_names);
|
||||
String[] descriptions = resources.getStringArray(R.array.color_mode_descriptions);
|
||||
// Map the resource information describing color modes.
|
||||
for (int i = 0; i < colorModes.length; i++) {
|
||||
if (colorModes[i] != -1 && i != 1 /* Skip Natural for now. */) {
|
||||
ColorModeDescription desc = new ColorModeDescription();
|
||||
desc.colorMode = colorModes[i];
|
||||
desc.title = titles[i];
|
||||
desc.summary = descriptions[i];
|
||||
mDescriptions.add(desc);
|
||||
}
|
||||
}
|
||||
mDescriptions = getColorModeDescriptions(getContext());
|
||||
|
||||
int currentColorMode = mDisplay.getColorMode();
|
||||
mCurrentIndex = -1;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -35,12 +36,47 @@ public abstract class DeveloperOptionsPreferenceController extends
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when developer options is enabled
|
||||
* Called when an activity returns to the DeveloperSettingsDashboardFragment.
|
||||
*
|
||||
* @param requestCode The integer request code originally supplied to
|
||||
* startActivityForResult(), allowing you to identify who this
|
||||
* result came from.
|
||||
* @param resultCode The integer result code returned by the child activity
|
||||
* through its setResult().
|
||||
* @param data An Intent, which can return result data to the caller
|
||||
* (various data can be attached to Intent "extras").
|
||||
* @return true if the controller handled the activity result
|
||||
*/
|
||||
public abstract void onDeveloperOptionsEnabled();
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*Called when developer options is disabled
|
||||
* Called when developer options is enabled
|
||||
*/
|
||||
public abstract void onDeveloperOptionsDisabled();
|
||||
public void onDeveloperOptionsEnabled() {
|
||||
if (isAvailable()) {
|
||||
onDeveloperOptionsSwitchEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when developer options is disabled
|
||||
*/
|
||||
public void onDeveloperOptionsDisabled() {
|
||||
if (isAvailable()) {
|
||||
onDeveloperOptionsSwitchDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when developer options is enabled and the preference is available
|
||||
*/
|
||||
protected abstract void onDeveloperOptionsSwitchEnabled();
|
||||
|
||||
/**
|
||||
* Called when developer options is disabled and the preference is available
|
||||
*/
|
||||
protected abstract void onDeveloperOptionsSwitchDisabled();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
/**
|
||||
* Interface for storing Activity request codes in development options
|
||||
*/
|
||||
public interface DevelopmentOptionsActivityRequestCodes {
|
||||
int REQUEST_CODE_ENABLE_OEM_UNLOCK = 0;
|
||||
}
|
||||
@@ -16,10 +16,13 @@
|
||||
|
||||
package com.android.settings.development;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
import android.widget.Switch;
|
||||
|
||||
@@ -40,7 +43,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment
|
||||
implements SwitchBar.OnSwitchChangeListener {
|
||||
implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost {
|
||||
|
||||
private static final String TAG = "DevSettingsDashboard";
|
||||
|
||||
@@ -103,6 +106,33 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOemUnlockDialogConfirmed() {
|
||||
final OemUnlockPreferenceController controller = getDevelopmentOptionsController(
|
||||
OemUnlockPreferenceController.class);
|
||||
controller.onOemUnlockConfirmed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOemUnlockDialogDismissed() {
|
||||
final OemUnlockPreferenceController controller = getDevelopmentOptionsController(
|
||||
OemUnlockPreferenceController.class);
|
||||
controller.onOemUnlockDismissed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
for (AbstractPreferenceController controller : mPreferenceControllers) {
|
||||
if (controller instanceof DeveloperOptionsPreferenceController) {
|
||||
if (((DeveloperOptionsPreferenceController) controller).onActivityResult(
|
||||
requestCode, resultCode, data)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
@@ -121,7 +151,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
mPreferenceControllers = buildPreferenceControllers(context, getLifecycle());
|
||||
mPreferenceControllers = buildPreferenceControllers(context, getActivity(), getLifecycle(),
|
||||
this /* devOptionsDashboardFragment */);
|
||||
return mPreferenceControllers;
|
||||
}
|
||||
|
||||
@@ -140,14 +171,92 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Lifecycle lifecycle) {
|
||||
Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
// take bug report
|
||||
// desktop backup password
|
||||
controllers.add(new StayAwakePreferenceController(context, lifecycle));
|
||||
// hdcp checking
|
||||
controllers.add(new BluetoothSnoopLogPreferenceController(context));
|
||||
|
||||
controllers.add(new OemUnlockPreferenceController(context, activity, fragment));
|
||||
// running services
|
||||
// convert to file encryption
|
||||
controllers.add(new PictureColorModePreferenceController(context, lifecycle));
|
||||
// webview implementation
|
||||
// cool color temperature
|
||||
// automatic system updates
|
||||
// system ui demo mode
|
||||
// quick settings developer tiles
|
||||
// usb debugging
|
||||
// revoke usb debugging authorizations
|
||||
// local terminal
|
||||
// bug report shortcut
|
||||
// select mock location app
|
||||
// enable view attribute inspection
|
||||
// select debug app
|
||||
// wait for debugger
|
||||
// verify apps over usb
|
||||
// logger buffer sizes
|
||||
// store logger data persistently on device
|
||||
// telephony monitor
|
||||
// camera laser sensor
|
||||
// camera HAL HDR+
|
||||
// feature flags
|
||||
// wireless display certification
|
||||
// enable wi-fi verbose logging
|
||||
// aggressive wifi to mobile handover
|
||||
// always allow wifi roam scans
|
||||
// mobile always active
|
||||
// tethering hardware acceleration
|
||||
// select usb configuration
|
||||
// show bluetooth devices without names
|
||||
// disable absolute volume
|
||||
// enable in-band ringing
|
||||
// bluetooth avrcp version
|
||||
// bluetooth audio codec
|
||||
// bluetooth audio sample rate
|
||||
// bluetooth audio bits per sample
|
||||
// bluetooth audio channel mode
|
||||
// bluetooth audio ldac codec: playback quality
|
||||
// show taps
|
||||
// pointer location
|
||||
// show surface updates
|
||||
// show layout bounds
|
||||
// force rtl layout direction
|
||||
// window animation scale
|
||||
// transition animation scale
|
||||
// animator duration scale
|
||||
// simulate secondary displays
|
||||
// smallest width
|
||||
// force gpu rendering
|
||||
// show gpu view updates
|
||||
// show hardware layers updates
|
||||
// debug gpu overdraw
|
||||
// debug non-rectangular clip operations
|
||||
// force 4x msaa
|
||||
// disable hw overlays
|
||||
// simulate color space
|
||||
// set gpu renderer
|
||||
// disable usb audio routing
|
||||
// strict mode enabled
|
||||
// profile gpu rendering
|
||||
// don't keep activities
|
||||
// background process limit
|
||||
// background check
|
||||
// show all anrs
|
||||
// show notification channel warnings
|
||||
// inactive apps
|
||||
// force allow apps on external
|
||||
// force activities to be resizable
|
||||
// reset shortcutmanager rate-limiting
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
<T extends AbstractPreferenceController> T getDevelopmentOptionsController(Class<T> clazz) {
|
||||
return getPreferenceController(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
@@ -171,7 +280,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context
|
||||
context) {
|
||||
return buildPreferenceControllers(context, null /* lifecycle */);
|
||||
return buildPreferenceControllers(context, null /* activity */,
|
||||
null /* lifecycle */, null /* devOptionsDashboardFragment */);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
public class EnableOemUnlockSettingWarningDialog extends InstrumentedDialogFragment implements
|
||||
DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
|
||||
|
||||
public static final String TAG = "EnableOemUnlockDlg";
|
||||
|
||||
public static void show(Fragment host) {
|
||||
final FragmentManager manager = host.getActivity().getFragmentManager();
|
||||
if (manager.findFragmentByTag(TAG) == null) {
|
||||
final EnableOemUnlockSettingWarningDialog dialog =
|
||||
new EnableOemUnlockSettingWarningDialog();
|
||||
dialog.setTargetFragment(host, 0 /* requestCode */);
|
||||
dialog.show(manager, TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DIALOG_ENABLE_OEM_UNLOCKING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.confirm_enable_oem_unlock_title)
|
||||
.setMessage(R.string.confirm_enable_oem_unlock_text)
|
||||
.setPositiveButton(R.string.enable_text, this /* onClickListener */)
|
||||
.setNegativeButton(android.R.string.cancel, this /* onClickListener */)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
final OemUnlockDialogHost host = (OemUnlockDialogHost) getTargetFragment();
|
||||
if (host == null) {
|
||||
return;
|
||||
}
|
||||
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||
host.onOemUnlockDialogConfirmed();
|
||||
} else {
|
||||
host.onOemUnlockDialogDismissed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
final OemUnlockDialogHost host = (OemUnlockDialogHost) getTargetFragment();
|
||||
if (host == null) {
|
||||
return;
|
||||
}
|
||||
host.onOemUnlockDialogDismissed();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
/**
|
||||
* Interface for OemUnlockDialogFragment callbacks.
|
||||
*/
|
||||
public interface OemUnlockDialogHost {
|
||||
|
||||
/**
|
||||
* Called when the user presses enable on the warning dialog.
|
||||
*/
|
||||
void onOemUnlockDialogConfirmed();
|
||||
|
||||
/**
|
||||
* Called when the user dismisses or cancels the warning dialog.
|
||||
*/
|
||||
void onOemUnlockDialogDismissed();
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
|
||||
.REQUEST_CODE_ENABLE_OEM_UNLOCK;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.service.oemlock.OemLockManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
public class OemUnlockPreferenceController extends DeveloperOptionsPreferenceController implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String PREFERENCE_KEY = "oem_unlock_enable";
|
||||
|
||||
private final OemLockManager mOemLockManager;
|
||||
private final UserManager mUserManager;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final DevelopmentSettingsDashboardFragment mFragment;
|
||||
private final ChooseLockSettingsHelper mChooseLockSettingsHelper;
|
||||
private RestrictedSwitchPreference mPreference;
|
||||
|
||||
public OemUnlockPreferenceController(Context context, Activity activity,
|
||||
DevelopmentSettingsDashboardFragment fragment) {
|
||||
super(context);
|
||||
mOemLockManager = (OemLockManager) context.getSystemService(Context.OEM_LOCK_SERVICE);
|
||||
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
|
||||
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
mFragment = fragment;
|
||||
if (activity != null || mFragment != null) {
|
||||
mChooseLockSettingsHelper = new ChooseLockSettingsHelper(activity, mFragment);
|
||||
} else {
|
||||
mChooseLockSettingsHelper = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mOemLockManager != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREFERENCE_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
mPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean isUnlocked = (Boolean) newValue;
|
||||
if (isUnlocked) {
|
||||
if (!showKeyguardConfirmation(mContext.getResources(),
|
||||
REQUEST_CODE_ENABLE_OEM_UNLOCK)) {
|
||||
confirmEnableOemUnlock();
|
||||
}
|
||||
} else {
|
||||
mOemLockManager.setOemUnlockAllowedByUser(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
mPreference.setChecked(mOemLockManager.isOemUnlockAllowed());
|
||||
updateOemUnlockSettingDescription();
|
||||
// Showing mEnableOemUnlock preference as device has persistent data block.
|
||||
mPreference.setDisabledByAdmin(null);
|
||||
mPreference.setEnabled(enableOemUnlockPreference());
|
||||
if (mPreference.isEnabled()) {
|
||||
// Check restriction, disable mEnableOemUnlock and apply policy transparency.
|
||||
mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (mPreference.isChecked()) {
|
||||
confirmEnableOemUnlock();
|
||||
} else {
|
||||
mOemLockManager.setOemUnlockAllowedByUser(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
handleDeveloperOptionsToggled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
handleDeveloperOptionsToggled();
|
||||
}
|
||||
|
||||
public void onOemUnlockConfirmed() {
|
||||
mOemLockManager.setOemUnlockAllowedByUser(true);
|
||||
}
|
||||
|
||||
public void onOemUnlockDismissed() {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
updateState(mPreference);
|
||||
}
|
||||
|
||||
private void handleDeveloperOptionsToggled() {
|
||||
mPreference.setEnabled(enableOemUnlockPreference());
|
||||
if (mPreference.isEnabled()) {
|
||||
// Check restriction, disable mEnableOemUnlock and apply policy transparency.
|
||||
mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOemUnlockSettingDescription() {
|
||||
int oemUnlockSummary = R.string.oem_unlock_enable_summary;
|
||||
if (isBootloaderUnlocked()) {
|
||||
oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked;
|
||||
} else if (isSimLockedDevice()) {
|
||||
oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device;
|
||||
} else if (!isOemUnlockAllowedByUserAndCarrier()) {
|
||||
// If the device isn't SIM-locked but OEM unlock is disallowed by some party, this
|
||||
// means either some other carrier restriction is in place or the device hasn't been
|
||||
// able to confirm which restrictions (SIM-lock or otherwise) apply.
|
||||
oemUnlockSummary =
|
||||
R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked;
|
||||
}
|
||||
mPreference.setSummary(mContext.getResources().getString(oemUnlockSummary));
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */
|
||||
private boolean isSimLockedDevice() {
|
||||
int phoneCount = mTelephonyManager.getPhoneCount();
|
||||
for (int i = 0; i < phoneCount; i++) {
|
||||
if (mTelephonyManager.getAllowedCarriers(i).size() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}.
|
||||
*/
|
||||
private boolean isBootloaderUnlocked() {
|
||||
return mOemLockManager.isDeviceOemUnlocked();
|
||||
}
|
||||
|
||||
private boolean enableOemUnlockPreference() {
|
||||
return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier();
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
boolean showKeyguardConfirmation(Resources resources, int requestCode) {
|
||||
return mChooseLockSettingsHelper.launchConfirmationActivity(
|
||||
requestCode, resources.getString(R.string.oem_unlock_enable));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void confirmEnableOemUnlock() {
|
||||
EnableOemUnlockSettingWarningDialog.show(mFragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether OEM unlock is allowed by the user and carrier.
|
||||
*
|
||||
* This does not take into account any restrictions imposed by the device policy.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isOemUnlockAllowedByUserAndCarrier() {
|
||||
final UserHandle userHandle = UserHandle.of(UserHandle.myUserId());
|
||||
return mOemLockManager.isOemUnlockAllowedByCarrier()
|
||||
&& !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET,
|
||||
userHandle);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
public class PictureColorModePreferenceController extends
|
||||
DeveloperOptionsPreferenceController implements
|
||||
LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_COLOR_MODE = "picture_color_mode";
|
||||
|
||||
private ColorModePreference mPreference;
|
||||
|
||||
public PictureColorModePreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return getColorModeDescriptionsSize() > 1 && !isWideColorGamut();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_COLOR_MODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = (ColorModePreference) screen.findPreference(getPreferenceKey());
|
||||
if (mPreference != null) {
|
||||
mPreference.updateCurrentAndSupported();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
mPreference.startListening();
|
||||
mPreference.updateCurrentAndSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mPreference == null) {
|
||||
return;
|
||||
}
|
||||
mPreference.stopListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
mPreference.setEnabled(false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isWideColorGamut() {
|
||||
return mContext.getDisplay().isWideColorGamut();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getColorModeDescriptionsSize() {
|
||||
return ColorModePreference.getColorModeDescriptions(mContext).size();
|
||||
}
|
||||
}
|
||||
@@ -100,19 +100,6 @@ public class StayAwakePreferenceController extends DeveloperOptionsPreferenceCon
|
||||
mPreference.setChecked(stayAwakeMode != SETTING_VALUE_OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeveloperOptionsEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeveloperOptionsDisabled() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, SETTING_VALUE_OFF);
|
||||
mPreference.setChecked(false);
|
||||
mPreference.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mPreference != null) {
|
||||
@@ -127,6 +114,19 @@ public class StayAwakePreferenceController extends DeveloperOptionsPreferenceCon
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, SETTING_VALUE_OFF);
|
||||
mPreference.setChecked(false);
|
||||
mPreference.setEnabled(false);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
RestrictedLockUtils.EnforcedAdmin checkIfMaximumTimeToLockSetByAdmin() {
|
||||
// A DeviceAdmin has specified a maximum time until the device
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.android.internal.app.NightDisplayController;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -58,11 +59,11 @@ public class NightDisplayPreference extends SwitchPreference
|
||||
mController.setListener(null);
|
||||
}
|
||||
|
||||
private String getFormattedTimeString(NightDisplayController.LocalTime localTime) {
|
||||
private String getFormattedTimeString(LocalTime localTime) {
|
||||
final Calendar c = Calendar.getInstance();
|
||||
c.setTimeZone(mTimeFormatter.getTimeZone());
|
||||
c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay);
|
||||
c.set(Calendar.MINUTE, localTime.minute);
|
||||
c.set(Calendar.HOUR_OF_DAY, localTime.getHour());
|
||||
c.set(Calendar.MINUTE, localTime.getMinute());
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
return mTimeFormatter.format(c.getTime());
|
||||
@@ -116,12 +117,12 @@ public class NightDisplayPreference extends SwitchPreference
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
|
||||
public void onCustomStartTimeChanged(LocalTime startTime) {
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
|
||||
public void onCustomEndTimeChanged(LocalTime endTime) {
|
||||
updateSummary();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.android.settings.widget.SeekBarPreference;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
@@ -144,7 +145,7 @@ public class NightDisplaySettings extends SettingsPreferenceFragment
|
||||
@Override
|
||||
public Dialog onCreateDialog(final int dialogId) {
|
||||
if (dialogId == DIALOG_START_TIME || dialogId == DIALOG_END_TIME) {
|
||||
final NightDisplayController.LocalTime initialTime;
|
||||
final LocalTime initialTime;
|
||||
if (dialogId == DIALOG_START_TIME) {
|
||||
initialTime = mController.getCustomStartTime();
|
||||
} else {
|
||||
@@ -156,15 +157,14 @@ public class NightDisplaySettings extends SettingsPreferenceFragment
|
||||
return new TimePickerDialog(context, new TimePickerDialog.OnTimeSetListener() {
|
||||
@Override
|
||||
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
|
||||
final NightDisplayController.LocalTime time =
|
||||
new NightDisplayController.LocalTime(hourOfDay, minute);
|
||||
final LocalTime time = LocalTime.of(hourOfDay, minute);
|
||||
if (dialogId == DIALOG_START_TIME) {
|
||||
mController.setCustomStartTime(time);
|
||||
} else {
|
||||
mController.setCustomEndTime(time);
|
||||
}
|
||||
}
|
||||
}, initialTime.hourOfDay, initialTime.minute, use24HourFormat);
|
||||
}, initialTime.getHour(), initialTime.getMinute(), use24HourFormat);
|
||||
}
|
||||
return super.onCreateDialog(dialogId);
|
||||
}
|
||||
@@ -201,11 +201,11 @@ public class NightDisplaySettings extends SettingsPreferenceFragment
|
||||
mTemperaturePreference.setProgress(convertTemperature(colorTemperature));
|
||||
}
|
||||
|
||||
private String getFormattedTimeString(NightDisplayController.LocalTime localTime) {
|
||||
private String getFormattedTimeString(LocalTime localTime) {
|
||||
final Calendar c = Calendar.getInstance();
|
||||
c.setTimeZone(mTimeFormatter.getTimeZone());
|
||||
c.set(Calendar.HOUR_OF_DAY, localTime.hourOfDay);
|
||||
c.set(Calendar.MINUTE, localTime.minute);
|
||||
c.set(Calendar.HOUR_OF_DAY, localTime.getHour());
|
||||
c.set(Calendar.MINUTE, localTime.getMinute());
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
return mTimeFormatter.format(c.getTime());
|
||||
@@ -221,12 +221,12 @@ public class NightDisplaySettings extends SettingsPreferenceFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomStartTimeChanged(NightDisplayController.LocalTime startTime) {
|
||||
public void onCustomStartTimeChanged(LocalTime startTime) {
|
||||
mStartTimePreference.setSummary(getFormattedTimeString(startTime));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCustomEndTimeChanged(NightDisplayController.LocalTime endTime) {
|
||||
public void onCustomEndTimeChanged(LocalTime endTime) {
|
||||
mEndTimePreference.setSummary(getFormattedTimeString(endTime));
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,9 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
|
||||
}
|
||||
|
||||
void updateDependents(boolean banned) {
|
||||
PreferenceGroup parent;
|
||||
if (mShowLegacyChannelConfig) {
|
||||
parent = getPreferenceScreen();
|
||||
setVisible(mImportanceToggle, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
} else {
|
||||
setVisible(mAdvanced, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
@@ -369,12 +371,13 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
|
||||
NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight());
|
||||
setVisible(mVibrate, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
|
||||
setVisible(mRingtone, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
|
||||
parent = mAdvanced;
|
||||
}
|
||||
setVisible(mAdvanced, mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
setVisible(mAdvanced, mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
setVisible(parent, mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
setVisible(parent, mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
|| (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
|
||||
&& mDndVisualEffectsSuppressed));
|
||||
setVisible(mAdvanced, mVisibilityOverride, isLockScreenSecure()
|
||||
setVisible(parent, mVisibilityOverride, isLockScreenSecure()
|
||||
&&checkCanBeVisible(NotificationManager.IMPORTANCE_LOW));
|
||||
setVisible(mBlockedDesc, mChannel.getImportance() == IMPORTANCE_NONE);
|
||||
if (mAppLink != null) {
|
||||
|
||||
@@ -1070,7 +1070,7 @@ public class WifiSettings extends RestrictedSettingsFragment
|
||||
|
||||
protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
|
||||
// Log subtype if configuration is a saved network.
|
||||
mMetricsFeatureProvider.action(getActivity(), MetricsEvent.ACTION_WIFI_CONNECT,
|
||||
mMetricsFeatureProvider.action(getVisibilityLogger(), MetricsEvent.ACTION_WIFI_CONNECT,
|
||||
isSavedNetwork);
|
||||
mWifiManager.connect(config, mConnectListener);
|
||||
mClickedConnect = true;
|
||||
|
||||
@@ -41,4 +41,8 @@ public class UserManagerWrapper {
|
||||
public List<UserInfo> getUsers() {
|
||||
return mUserManager.getUsers();
|
||||
}
|
||||
|
||||
public List<UserInfo> getProfiles(int userHandle) {
|
||||
return mUserManager.getProfiles(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.applications;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.wrapper.UserManagerWrapper;
|
||||
import com.android.settingslib.wrapper.PackageManagerWrapper;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class PictureInPictureSettingsTest {
|
||||
|
||||
private static final int PRIMARY_USER_ID = 0;
|
||||
private static final int PROFILE_USER_ID = 10;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private PictureInPictureSettings mFragment;
|
||||
@Mock
|
||||
private PackageManagerWrapper mPackageManager;
|
||||
@Mock
|
||||
private UserManagerWrapper mUserManager;
|
||||
private ArrayList<PackageInfo> mPrimaryUserPackages;
|
||||
private ArrayList<PackageInfo> mProfileUserPackages;
|
||||
private ArrayList<UserInfo> mUsers;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
FakeFeatureFactory.setupForTest(mContext);
|
||||
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
|
||||
mFragment = new PictureInPictureSettings(mPackageManager, mUserManager);
|
||||
mPrimaryUserPackages = new ArrayList<>();
|
||||
mProfileUserPackages = new ArrayList<>();
|
||||
mUsers = new ArrayList<>();
|
||||
when(mPackageManager.getInstalledPackagesAsUser(anyInt(), eq(PRIMARY_USER_ID)))
|
||||
.thenReturn(mPrimaryUserPackages);
|
||||
when(mPackageManager.getInstalledPackagesAsUser(anyInt(), eq(PROFILE_USER_ID)))
|
||||
.thenReturn(mProfileUserPackages);
|
||||
when(mUserManager.getProfiles(anyInt())).thenReturn(mUsers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectPipApps() {
|
||||
PackageInfo primaryP1 = createPackage("Calculator", true);
|
||||
PackageInfo primaryP2 = createPackage("Clock", false);
|
||||
PackageInfo profileP1 = createPackage("Calculator", false);
|
||||
PackageInfo profileP2 = createPackage("Clock", true);
|
||||
|
||||
mPrimaryUserPackages.add(primaryP1);
|
||||
mPrimaryUserPackages.add(primaryP2);
|
||||
mProfileUserPackages.add(profileP1);
|
||||
mProfileUserPackages.add(profileP2);
|
||||
|
||||
ArrayList<Pair<ApplicationInfo, Integer>> apps = mFragment.collectPipApps(PRIMARY_USER_ID);
|
||||
assertThat(containsPackages(apps, primaryP1, profileP2));
|
||||
assertThat(!containsPackages(apps, primaryP2, profileP1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppSort() {
|
||||
PackageInfo primaryP1 = createPackage("Android", true);
|
||||
PackageInfo primaryP2 = createPackage("Boop", true);
|
||||
PackageInfo primaryP3 = createPackage("Deck", true);
|
||||
PackageInfo profileP1 = createPackage("Android", true);
|
||||
PackageInfo profileP2 = createPackage("Cool", true);
|
||||
PackageInfo profileP3 = createPackage("Fast", false);
|
||||
|
||||
mPrimaryUserPackages.add(primaryP1);
|
||||
mPrimaryUserPackages.add(primaryP2);
|
||||
mPrimaryUserPackages.add(primaryP3);
|
||||
mProfileUserPackages.add(profileP1);
|
||||
mProfileUserPackages.add(profileP2);
|
||||
mProfileUserPackages.add(profileP3);
|
||||
|
||||
ArrayList<Pair<ApplicationInfo, Integer>> apps = mFragment.collectPipApps(PRIMARY_USER_ID);
|
||||
Collections.sort(apps, new PictureInPictureSettings.AppComparator(null));
|
||||
assertThat(isOrdered(apps, primaryP1, profileP1, primaryP2, profileP2));
|
||||
}
|
||||
|
||||
private boolean containsPackages(ArrayList<Pair<ApplicationInfo, Integer>> apps,
|
||||
PackageInfo... packages) {
|
||||
for (int i = 0; i < packages.length; i++) {
|
||||
boolean found = false;
|
||||
for (int j = 0; j < apps.size(); j++) {
|
||||
if (apps.get(j).first == packages[i].applicationInfo) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isOrdered(ArrayList<Pair<ApplicationInfo, Integer>> apps,
|
||||
PackageInfo... packages) {
|
||||
if (apps.size() != packages.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < packages.length; i++) {
|
||||
if (packages[i].applicationInfo != apps.get(i).first) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private PackageInfo createPackage(String appTitle, boolean supportsPip) {
|
||||
PackageInfo pi = new PackageInfo();
|
||||
ActivityInfo ai = new ActivityInfo();
|
||||
if (supportsPip) {
|
||||
ai.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
|
||||
}
|
||||
pi.activities = new ActivityInfo[1];
|
||||
pi.activities[0] = ai;
|
||||
pi.applicationInfo = new ApplicationInfo();
|
||||
pi.applicationInfo.name = appTitle;
|
||||
return pi;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
@@ -65,4 +66,11 @@ public class UsageAccessDetailsTest {
|
||||
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
|
||||
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_USAGE_VIEW_DENY), eq("app"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void refreshUi_nullPackageInfo_shouldNotCrash() throws RemoteException {
|
||||
mFragment.mPackageInfo = null;
|
||||
mFragment.refreshUi();
|
||||
// should not crash
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,25 @@ package com.android.settings.bluetooth;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.widget.SummaryUpdater.OnSummaryChangeListener;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -39,19 +47,9 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class BluetoothSummaryUpdaterTest {
|
||||
@@ -70,16 +68,33 @@ public class BluetoothSummaryUpdaterTest {
|
||||
@Mock
|
||||
private SummaryListener mListener;
|
||||
|
||||
// Disabled by default
|
||||
private final boolean[] mAdapterEnabled = {false};
|
||||
// Not connected by default
|
||||
private final int[] mAdapterConnectionState = {BluetoothAdapter.STATE_DISCONNECTED};
|
||||
// Not connected by default
|
||||
private final boolean[] mDeviceConnected = {false, false};
|
||||
private final Set<BluetoothDevice> mBondedDevices = new HashSet<>();
|
||||
private BluetoothSummaryUpdater mSummaryUpdater;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBtAdapter);
|
||||
when(mBtAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
|
||||
mContext = RuntimeEnvironment.application.getApplicationContext();
|
||||
doCallRealMethod().when(mListener).onSummaryChanged(anyString());
|
||||
// Setup mock adapter
|
||||
when(mBluetoothManager.getBluetoothAdapter()).thenReturn(mBtAdapter);
|
||||
doAnswer(invocation -> mAdapterEnabled[0]).when(mBtAdapter).isEnabled();
|
||||
doAnswer(invocation -> mAdapterConnectionState[0]).when(mBtAdapter).getConnectionState();
|
||||
mSummaryUpdater = new BluetoothSummaryUpdater(mContext, mListener, mBluetoothManager);
|
||||
// Setup first device
|
||||
doReturn(DEVICE_NAME).when(mConnectedDevice).getName();
|
||||
doAnswer(invocation -> mDeviceConnected[0]).when(mConnectedDevice).isConnected();
|
||||
// Setup second device
|
||||
doReturn(DEVICE_KEYBOARD_NAME).when(mConnectedKeyBoardDevice).getName();
|
||||
doAnswer(invocation -> mDeviceConnected[1]).when(mConnectedKeyBoardDevice)
|
||||
.isConnected();
|
||||
doReturn(mBondedDevices).when(mBtAdapter).getBondedDevices();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -98,7 +113,10 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void register_true_shouldSendSummaryChange() {
|
||||
prepareConnectedDevice(false);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
|
||||
mSummaryUpdater.register(true);
|
||||
|
||||
@@ -108,7 +126,11 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_btDisabled_shouldSendDisabledSummary() {
|
||||
mSummaryUpdater.register(true);
|
||||
// These states should be ignored
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
|
||||
@@ -116,68 +138,83 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_btEnabled_connected_shouldSendConnectedSummary() {
|
||||
prepareConnectedDevice(false);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
|
||||
mSummaryUpdater.register(true);
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
verify(mListener).onSummaryChanged(
|
||||
mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_btEnabled_connectedMisMatch_shouldSendNotConnected() {
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
// State mismatch
|
||||
mDeviceConnected[0] = false;
|
||||
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
|
||||
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_btEnabled_notConnected_shouldSendDisconnectedMessage() {
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
|
||||
mSummaryUpdater.register(true);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
// This should be ignored
|
||||
mDeviceConnected[0] = true;
|
||||
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
|
||||
|
||||
verify(mListener).onSummaryChanged(
|
||||
mContext.getString(R.string.disconnected));
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBluetoothStateChanged_ConnectedDisabledEnabled_shouldSendDisconnectedSummary() {
|
||||
final boolean[] connected = {false};
|
||||
final List<CachedBluetoothDevice> devices = new ArrayList<>();
|
||||
devices.add(mock(CachedBluetoothDevice.class));
|
||||
doAnswer(invocation -> connected[0]).when(devices.get(0)).isConnected();
|
||||
when(mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy())
|
||||
.thenReturn(devices);
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
|
||||
prepareConnectedDevice(false);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = false;
|
||||
|
||||
mSummaryUpdater.register(true);
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
|
||||
|
||||
connected[0] = true;
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mDeviceConnected[0] = true;
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_CONNECTED);
|
||||
verify(mListener).onSummaryChanged(
|
||||
mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
|
||||
|
||||
mAdapterEnabled[0] = false;
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_OFF);
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
|
||||
|
||||
connected[0] = false;
|
||||
// Turning ON means not enabled
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
|
||||
// There should still be only one invocation of disabled message
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disabled));
|
||||
|
||||
mAdapterEnabled[0] = true;
|
||||
mDeviceConnected[0] = false;
|
||||
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
|
||||
verify(mListener, times(2)).onSummaryChanged(mContext.getString(R.string.disconnected));
|
||||
verify(mListener, times(4)).onSummaryChanged(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConnectionStateChanged_connected_shouldSendConnectedMessage() {
|
||||
final List<CachedBluetoothDevice> devices = new ArrayList<>();
|
||||
devices.add(mock(CachedBluetoothDevice.class));
|
||||
when(devices.get(0).isConnected()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy())
|
||||
.thenReturn(devices);
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
|
||||
prepareConnectedDevice(false);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
|
||||
mSummaryUpdater.register(true);
|
||||
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_CONNECTED);
|
||||
|
||||
@@ -187,7 +224,22 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void onConnectionStateChanged_inconsistentState_shouldSendDisconnectedMessage() {
|
||||
mSummaryUpdater.register(true);
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTED;
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = false;
|
||||
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_CONNECTED);
|
||||
|
||||
verify(mListener).onSummaryChanged(mContext.getString(R.string.disconnected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onConnectionStateChanged_noBondedDevice_shouldSendDisconnectedMessage() {
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTED;
|
||||
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_CONNECTED);
|
||||
|
||||
@@ -197,8 +249,10 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void onConnectionStateChanged_connecting_shouldSendConnectingMessage() {
|
||||
mSummaryUpdater.register(true);
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTING);
|
||||
// No need for bonded devices
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_CONNECTING;
|
||||
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_CONNECTING);
|
||||
|
||||
@@ -207,8 +261,10 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void onConnectionStateChanged_disconnecting_shouldSendDisconnectingMessage() {
|
||||
mSummaryUpdater.register(true);
|
||||
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTING);
|
||||
// No need for bonded devices
|
||||
mAdapterEnabled[0] = true;
|
||||
mAdapterConnectionState[0] = BluetoothAdapter.STATE_DISCONNECTING;
|
||||
|
||||
mSummaryUpdater.onConnectionStateChanged(null /* device */,
|
||||
BluetoothAdapter.STATE_DISCONNECTING);
|
||||
|
||||
@@ -217,7 +273,8 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void getConnectedDeviceSummary_hasConnectedDevice_returnOneDeviceSummary() {
|
||||
prepareConnectedDevice(false);
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
final String expectedSummary = mContext.getString(R.string.bluetooth_connected_summary,
|
||||
DEVICE_NAME);
|
||||
|
||||
@@ -226,28 +283,16 @@ public class BluetoothSummaryUpdaterTest {
|
||||
|
||||
@Test
|
||||
public void getConnectedDeviceSummary_multipleDevices_returnMultipleDevicesSummary() {
|
||||
prepareConnectedDevice(true);
|
||||
mBondedDevices.add(mConnectedDevice);
|
||||
mBondedDevices.add(mConnectedKeyBoardDevice);
|
||||
mDeviceConnected[0] = true;
|
||||
mDeviceConnected[1] = true;
|
||||
final String expectedSummary = mContext.getString(
|
||||
R.string.bluetooth_connected_multiple_devices_summary);
|
||||
|
||||
assertThat(mSummaryUpdater.getConnectedDeviceSummary()).isEqualTo(expectedSummary);
|
||||
}
|
||||
|
||||
private void prepareConnectedDevice(boolean multipleDevices) {
|
||||
final Set<BluetoothDevice> devices = new HashSet<>();
|
||||
doReturn(DEVICE_NAME).when(mConnectedDevice).getName();
|
||||
doReturn(true).when(mConnectedDevice).isConnected();
|
||||
devices.add(mConnectedDevice);
|
||||
if (multipleDevices) {
|
||||
// Add one more device if we need to test multiple devices
|
||||
doReturn(DEVICE_KEYBOARD_NAME).when(mConnectedKeyBoardDevice).getName();
|
||||
doReturn(true).when(mConnectedKeyBoardDevice).isConnected();
|
||||
devices.add(mConnectedKeyBoardDevice);
|
||||
}
|
||||
|
||||
doReturn(devices).when(mBtAdapter).getBondedDevices();
|
||||
}
|
||||
|
||||
private class SummaryListener implements OnSummaryChangeListener {
|
||||
String summary;
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ import com.android.settings.overlay.FeatureFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
@@ -42,24 +44,35 @@ import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class MetricsFeatureProviderTest {
|
||||
private static int CATEGORY = 10;
|
||||
private static boolean SUBTYPE_BOOLEAN = true;
|
||||
private static int SUBTYPE_INTEGER = 1;
|
||||
private static long ELAPSED_TIME = 1000;
|
||||
|
||||
@Mock private LogWriter mockLogWriter;
|
||||
@Mock private VisibilityLoggerMixin mockVisibilityLogger;
|
||||
|
||||
@Mock
|
||||
private LogWriter mLogWriter;
|
||||
private Context mContext;
|
||||
private MetricsFeatureProvider mProvider;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Pair> mPairCaptor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mProvider = new MetricsFeatureProvider();
|
||||
List<LogWriter> writers = new ArrayList<>();
|
||||
writers.add(mLogWriter);
|
||||
writers.add(mockLogWriter);
|
||||
ReflectionHelpers.setField(mProvider, "mLoggerWriters", writers);
|
||||
|
||||
when(mockVisibilityLogger.elapsedTimeSinceVisible()).thenReturn(ELAPSED_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -77,7 +90,7 @@ public class MetricsFeatureProviderTest {
|
||||
mProvider.logDashboardStartIntent(mContext, null /* intent */,
|
||||
MetricsEvent.SETTINGS_GESTURES);
|
||||
|
||||
verifyNoMoreInteractions(mLogWriter);
|
||||
verifyNoMoreInteractions(mockLogWriter);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,7 +99,7 @@ public class MetricsFeatureProviderTest {
|
||||
|
||||
mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
|
||||
|
||||
verify(mLogWriter).action(
|
||||
verify(mockLogWriter).action(
|
||||
eq(mContext),
|
||||
eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
|
||||
anyString(),
|
||||
@@ -99,10 +112,32 @@ public class MetricsFeatureProviderTest {
|
||||
|
||||
mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
|
||||
|
||||
verify(mLogWriter).action(
|
||||
verify(mockLogWriter).action(
|
||||
eq(mContext),
|
||||
eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
|
||||
anyString(),
|
||||
eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void action_BooleanLogsElapsedTime() {
|
||||
mProvider.action(mockVisibilityLogger, CATEGORY, SUBTYPE_BOOLEAN);
|
||||
verify(mockLogWriter).action(eq(CATEGORY), eq(SUBTYPE_BOOLEAN), mPairCaptor.capture());
|
||||
|
||||
Pair value = mPairCaptor.getValue();
|
||||
assertThat(value.first instanceof Integer).isTrue();
|
||||
assertThat((int) value.first).isEqualTo(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS);
|
||||
assertThat(value.second).isEqualTo(ELAPSED_TIME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void action_IntegerLogsElapsedTime() {
|
||||
mProvider.action(mockVisibilityLogger, CATEGORY, SUBTYPE_INTEGER);
|
||||
verify(mockLogWriter).action(eq(CATEGORY), eq(SUBTYPE_INTEGER), mPairCaptor.capture());
|
||||
|
||||
Pair value = mPairCaptor.getValue();
|
||||
assertThat(value.first instanceof Integer).isTrue();
|
||||
assertThat((int) value.first).isEqualTo(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS);
|
||||
assertThat(value.second).isEqualTo(ELAPSED_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ public class SuggestionAdapterTest {
|
||||
public void onBindViewHolder_v2_itemViewShouldHandleClick()
|
||||
throws PendingIntent.CanceledException {
|
||||
final List<Suggestion> packages = makeSuggestionsV2("pkg1");
|
||||
setupSuggestions(mActivity, null /* suggestionV1 */ , packages);
|
||||
setupSuggestions(mActivity, null /* suggestionV1 */, packages);
|
||||
|
||||
mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0);
|
||||
mSuggestionHolder.itemView.performClick();
|
||||
@@ -233,6 +233,22 @@ public class SuggestionAdapterTest {
|
||||
assertThat(itemView.getChildCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSuggestionsV2_shouldReturnSuggestionWhenMatch() {
|
||||
final List<Suggestion> suggestionsV2 = makeSuggestionsV2("pkg1");
|
||||
setupSuggestions(mActivity, null /* suggestionV1 */, suggestionsV2);
|
||||
|
||||
assertThat(mSuggestionAdapter.getSuggestion(0)).isNull();
|
||||
assertThat(mSuggestionAdapter.getSuggestionsV2(0)).isNotNull();
|
||||
|
||||
List<Tile> suggestionsV1 = makeSuggestions("pkg1");
|
||||
setupSuggestions(mActivity, suggestionsV1, null /* suggestionV2 */);
|
||||
|
||||
assertThat(mSuggestionAdapter.getSuggestionsV2(0)).isNull();
|
||||
assertThat(mSuggestionAdapter.getSuggestion(0)).isNotNull();
|
||||
|
||||
}
|
||||
|
||||
private void setupSuggestions(Context context, List<Tile> suggestions,
|
||||
List<Suggestion> suggestionsV2) {
|
||||
mSuggestionAdapter = new SuggestionAdapter(context, suggestions, suggestionsV2,
|
||||
|
||||
@@ -72,6 +72,7 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -430,14 +431,35 @@ public class SuggestionFeatureProviderImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasUsedNightDisplay_returnsTrue_ifPreviouslyActivated() {
|
||||
Secure.putLong(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, 1L);
|
||||
public void hasUsedNightDisplay_returnsTrue_ifPreviouslyActivatedAndManual() {
|
||||
Secure.putString(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
|
||||
LocalDateTime.now().toString());
|
||||
Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE, 1);
|
||||
assertThat(mProvider.hasUsedNightDisplay(mContext)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nightDisplaySuggestion_isCompleted_ifPreviouslyActivated() {
|
||||
Secure.putLong(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, 1L);
|
||||
Secure.putString(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
|
||||
LocalDateTime.now().toString());
|
||||
final ComponentName componentName =
|
||||
new ComponentName(mContext, NightDisplaySuggestionActivity.class);
|
||||
assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nightDisplaySuggestion_isCompleted_ifNonManualMode() {
|
||||
Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE, 1);
|
||||
final ComponentName componentName =
|
||||
new ComponentName(mContext, NightDisplaySuggestionActivity.class);
|
||||
assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nightDisplaySuggestion_isCompleted_ifPreviouslyCleared() {
|
||||
Secure.putString(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME,
|
||||
null);
|
||||
Secure.putInt(mContext.getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE, 1);
|
||||
final ComponentName componentName =
|
||||
new ComponentName(mContext, NightDisplaySuggestionActivity.class);
|
||||
assertThat(mProvider.isSuggestionCompleted(mContext, componentName)).isTrue();
|
||||
|
||||
@@ -17,7 +17,11 @@
|
||||
package com.android.settings.development;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -108,6 +112,9 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = {
|
||||
ShadowPictureColorModePreferenceController.class
|
||||
})
|
||||
public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
|
||||
final Context appContext = RuntimeEnvironment.application;
|
||||
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
|
||||
@@ -161,6 +168,24 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() {
|
||||
final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
|
||||
doReturn(controller).when(mDashboard).getDevelopmentOptionsController(
|
||||
OemUnlockPreferenceController.class);
|
||||
mDashboard.onOemUnlockDialogConfirmed();
|
||||
verify(controller).onOemUnlockConfirmed();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed() {
|
||||
final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class);
|
||||
doReturn(controller).when(mDashboard).getDevelopmentOptionsController(
|
||||
OemUnlockPreferenceController.class);
|
||||
mDashboard.onOemUnlockDialogDismissed();
|
||||
verify(controller).onOemUnlockDismissed();
|
||||
}
|
||||
|
||||
@Implements(EnableDevelopmentSettingWarningDialog.class)
|
||||
public static class ShadowEnableDevelopmentSettingWarningDialog {
|
||||
|
||||
@@ -176,4 +201,13 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
||||
mShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Implements(PictureColorModePreferenceController.class)
|
||||
public static class ShadowPictureColorModePreferenceController {
|
||||
|
||||
@Implementation
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
|
||||
.REQUEST_CODE_ENABLE_OEM_UNLOCK;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserManager;
|
||||
import android.service.oemlock.OemLockManager;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class OemUnlockPreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private Activity mActivity;
|
||||
@Mock
|
||||
private DevelopmentSettingsDashboardFragment mFragment;
|
||||
@Mock
|
||||
private RestrictedSwitchPreference mPreference;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@Mock
|
||||
private OemLockManager mOemLockManager;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
private OemUnlockPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mContext.getSystemService(Context.OEM_LOCK_SERVICE)).thenReturn(mOemLockManager);
|
||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
mController = new OemUnlockPreferenceController(mContext, mActivity, mFragment);
|
||||
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
|
||||
mPreference);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnTrueWhenOemLockManagerIsNotNull() {
|
||||
boolean returnValue = mController.isAvailable();
|
||||
|
||||
assertThat(returnValue).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnFalseWhenOemLockManagerIsNull() {
|
||||
when(mContext.getSystemService(Context.OEM_LOCK_SERVICE)).thenReturn(null);
|
||||
mController = new OemUnlockPreferenceController(mContext, mActivity, mFragment);
|
||||
boolean returnValue = mController.isAvailable();
|
||||
|
||||
assertThat(returnValue).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChanged_turnOnUnlock() {
|
||||
mController = spy(mController);
|
||||
doReturn(false).when(mController).showKeyguardConfirmation(mResources,
|
||||
REQUEST_CODE_ENABLE_OEM_UNLOCK);
|
||||
doNothing().when(mController).confirmEnableOemUnlock();
|
||||
mController.onPreferenceChange(null, true);
|
||||
|
||||
verify(mController).confirmEnableOemUnlock();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChanged_turnOffUnlock() {
|
||||
mController.onPreferenceChange(null, false);
|
||||
|
||||
verify(mOemLockManager).setOemUnlockAllowedByUser(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_preferenceShouldBeCheckedAndShouldBeDisabled() {
|
||||
mController = spy(mController);
|
||||
when(mOemLockManager.isOemUnlockAllowed()).thenReturn(true);
|
||||
doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier();
|
||||
when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(true);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(true);
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_preferenceShouldBeUncheckedAndShouldBeDisabled() {
|
||||
mController = spy(mController);
|
||||
when(mOemLockManager.isOemUnlockAllowed()).thenReturn(false);
|
||||
doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier();
|
||||
when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(true);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(false);
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_preferenceShouldBeCheckedAndShouldBeEnabled() {
|
||||
mController = spy(mController);
|
||||
when(mOemLockManager.isOemUnlockAllowed()).thenReturn(true);
|
||||
doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier();
|
||||
when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(false);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
verify(mPreference).setChecked(true);
|
||||
verify(mPreference).setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_shouldReturnTrue() {
|
||||
final boolean result = mController.onActivityResult(REQUEST_CODE_ENABLE_OEM_UNLOCK,
|
||||
Activity.RESULT_OK, null);
|
||||
|
||||
assertThat(result).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onActivityResult_shouldReturnFalse() {
|
||||
final boolean result = mController.onActivityResult(123454,
|
||||
1434, null);
|
||||
|
||||
assertThat(result).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsEnabled_preferenceShouldCheckRestriction() {
|
||||
mController = spy(mController);
|
||||
doReturn(false).when(mController).isOemUnlockAllowedByUserAndCarrier();
|
||||
when(mPreference.isEnabled()).thenReturn(true);
|
||||
mController.onDeveloperOptionsEnabled();
|
||||
|
||||
verify(mPreference).checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionsDisabled_preferenceShouldCheckRestriction() {
|
||||
mController = spy(mController);
|
||||
doReturn(false).when(mController).isOemUnlockAllowedByUserAndCarrier();
|
||||
when(mPreference.isEnabled()).thenReturn(true);
|
||||
mController.onDeveloperOptionsDisabled();
|
||||
|
||||
verify(mPreference).checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onOemUnlockConfirmed_oemManagerShouldSetUnlockAllowedByUser() {
|
||||
mController.onOemUnlockConfirmed();
|
||||
|
||||
verify(mOemLockManager).setOemUnlockAllowedByUser(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.development;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class PictureColorModePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private ColorModePreference mPreference;
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private PreferenceScreen mPreferenceScreen;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
|
||||
private Lifecycle mLifecycle;
|
||||
private PictureColorModePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mLifecycle = new Lifecycle();
|
||||
mController = new PictureColorModePreferenceController(mContext, mLifecycle);
|
||||
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
|
||||
mPreference);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getIntArray(R.array.color_mode_ids)).thenReturn(new int[0]);
|
||||
mController.displayPreference(mPreferenceScreen);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnFalseWhenWideColorGambit() {
|
||||
mController = spy(mController);
|
||||
doReturn(2).when(mController).getColorModeDescriptionsSize();
|
||||
doReturn(true).when(mController).isWideColorGamut();
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnTrueWhenNotWideColorGambit() {
|
||||
mController = spy(mController);
|
||||
doReturn(2).when(mController).getColorModeDescriptionsSize();
|
||||
doReturn(false).when(mController).isWideColorGamut();
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnFalseWhenColorCountIsOne() {
|
||||
mController = spy(mController);
|
||||
doReturn(1).when(mController).getColorModeDescriptionsSize();
|
||||
doReturn(true).when(mController).isWideColorGamut();
|
||||
|
||||
assertThat(mController.isAvailable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_shouldReturnTrueWhenColorCountIsTwo() {
|
||||
mController = spy(mController);
|
||||
doReturn(2).when(mController).getColorModeDescriptionsSize();
|
||||
doReturn(false).when(mController).isWideColorGamut();
|
||||
|
||||
assertThat(mController.isAvailable()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionEnabled_shouldEnablePreference() {
|
||||
mController = spy(mController);
|
||||
doReturn(true).when(mController).isAvailable();
|
||||
mController.onDeveloperOptionsEnabled();
|
||||
|
||||
verify(mPreference).setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDeveloperOptionDisabled_shouldDisablePreference() {
|
||||
mController = spy(mController);
|
||||
doReturn(true).when(mController).isAvailable();
|
||||
mController.onDeveloperOptionsDisabled();
|
||||
|
||||
verify(mPreference).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onResume_shouldStartListening() {
|
||||
mLifecycle.onResume();
|
||||
|
||||
verify(mPreference).startListening();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPause_shouldStopListening() {
|
||||
mLifecycle.onPause();
|
||||
|
||||
verify(mPreference).stopListening();
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,11 @@ public class ShadowSecureSettings {
|
||||
int userHandle) {
|
||||
final Table<Integer, String, Object> userTable = getUserTable(resolver);
|
||||
synchronized (userTable) {
|
||||
userTable.put(userHandle, name, value);
|
||||
if (value != null) {
|
||||
userTable.put(userHandle, name, value);
|
||||
} else {
|
||||
userTable.remove(userHandle, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user