Snap for 4380820 from 80fd58e3b6 to pi-release

Change-Id: Ic921607522c8e96ea9189c21dd7c468502729869
This commit is contained in:
android-build-team Robot
2017-10-06 08:03:26 +00:00
37 changed files with 1658 additions and 286 deletions

View File

@@ -33,26 +33,27 @@
android:layout_width="@dimen/dashboard_tile_image_size"
android:layout_height="@dimen/dashboard_tile_image_size"
android:layout_marginStart="14dp"
android:layout_marginEnd="24dp"/>
android:layout_marginEnd="24dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:id="@android:id/title"
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.TileTitle"
android:ellipsize="marquee"
android:fadingEdge="horizontal"/>
android:fadingEdge="horizontal" />
<TextView android:id="@android:id/summary"
<TextView
android:id="@android:id/summary"
android:textAppearance="@style/TextAppearance.SuggestionSummary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Small"
android:textColor="?android:attr/textColorSecondary"/>
android:layout_height="wrap_content" />
</LinearLayout>

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="12dp"
android:paddingBottom="20dp"
android:paddingTop="16dp"
android:orientation="horizontal"
android:minHeight="@dimen/dashboard_tile_minimum_height">
<ImageView
android:id="@android:id/icon"
android:layout_width="@dimen/dashboard_tile_image_size"
android:layout_height="@dimen/dashboard_tile_image_size"
android:contentDescription="@null" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_marginStart="18dp"
android:layout_marginTop="2dp"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<TextView
style="@style/TextAppearance.SuggestionTitle"
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginStart="6dp"
android:layout_marginEnd="50dp"
android:textAppearance="@style/TextAppearance.SuggestionSummary" />
<Button
android:id="@android:id/primary"
style="@style/SuwGlifButton.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/suggestion_button_text" />
</LinearLayout>
</LinearLayout>

View File

@@ -7321,6 +7321,8 @@
settings button -->
<string name="notification_app_settings_button">Notification settings</string>
<!-- Generic label for suggestion card's ok button [CHAR LIMIT=20] -->
<string name="suggestion_button_text">Ok</string>
<!-- [CHAR LIMIT=35] Feedback on the device -->
<string name="device_feedback">Send feedback about this device</string>

View File

@@ -318,7 +318,10 @@
<style name="TextAppearance.SuggestionTitle"
parent="@android:style/TextAppearance.Material.Subhead">
<item name="android:fontFamily">sans-serif-medium</item>
<item name="android:textSize">14sp</item>
</style>
<style name="TextAppearance.SuggestionSummary" parent="TextAppearance.Small">
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.FingerprintErrorText"

View File

@@ -29,12 +29,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
import com.android.settings.core.TouchOverlayManager;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -60,8 +61,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
private Intent mSettingsIntent;
private OverlayState mOverlayState;
private TouchOverlayManager mTouchOverlayManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,7 +68,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
Context context = getActivity();
mOverlayBridge = new AppStateOverlayBridge(context, mState, null);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mTouchOverlayManager = new TouchOverlayManager(context);
// find preferences
addPreferencesFromResource(R.xml.app_ops_permissions_details);
@@ -92,17 +90,17 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
}
@Override
public void onStart() {
super.onStart();
mTouchOverlayManager.setOverlayAllowed(false);
public void onResume() {
super.onResume();
getActivity().getWindow().addFlags(
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
}
@Override
public void onStop() {
super.onStop();
mTouchOverlayManager.setOverlayAllowed(true);
public void onPause() {
getActivity().getWindow().clearFlags(
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onPause();
}
@Override
@@ -153,16 +151,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
.getMetricsFeatureProvider().action(getContext(), logCategory, packageName);
}
private boolean canDrawOverlay(String pkgName) {
int result = mAppOpsManager.noteOpNoThrow(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
mPackageInfo.applicationInfo.uid, pkgName);
if (result == AppOpsManager.MODE_ALLOWED) {
return true;
}
return false;
}
@Override
protected boolean refreshUi() {
mOverlayState = mOverlayBridge.getOverlayInfo(mPackageName,

View File

@@ -1,40 +0,0 @@
/*
* 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.core;
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
public class TouchOverlayManager {
private final Context mContext;
private final IBinder mToken = new Binder();
public TouchOverlayManager(Context context) {
mContext = context;
}
public void setOverlayAllowed(boolean allowed) {
final AppOpsManager aom = mContext.getSystemService(AppOpsManager.class);
if (aom != null) {
aom.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW, !allowed, mToken);
aom.setUserRestriction(AppOpsManager.OP_TOAST_WINDOW, !allowed, mToken);
}
}
}

View File

@@ -44,7 +44,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
private final Context mContext;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final SuggestionFeatureProvider mSuggestionFeatureProvider;
@Deprecated // in favor of mNewSuggestions
@Deprecated // in favor of mSuggestionsV2
private final List<Tile> mSuggestions;
private final List<Suggestion> mSuggestionsV2;
private final IconCache mCache;
@@ -88,23 +88,15 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id);
mSuggestionsShownLogged.add(id);
}
// TODO: Add remote view field in Suggestion, and enable this.
// if (suggestion.remoteViews != null) {
// final ViewGroup itemView = (ViewGroup) holder.itemView;
// itemView.removeAllViews();
// itemView.addView(suggestion.remoteViews.apply(itemView.getContext(),
// itemView));
// } else
{
holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
holder.title.setText(suggestion.getTitle());
final CharSequence summary = suggestion.getSummary();
if (!TextUtils.isEmpty(summary)) {
holder.summary.setText(summary);
holder.summary.setVisibility(View.VISIBLE);
} else {
holder.summary.setVisibility(View.GONE);
}
holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
holder.title.setText(suggestion.getTitle());
final CharSequence summary = suggestion.getSummary();
if (!TextUtils.isEmpty(summary)) {
holder.summary.setText(summary);
holder.summary.setVisibility(View.VISIBLE);
} else {
holder.summary.setVisibility(View.GONE);
}
final View divider = holder.itemView.findViewById(R.id.divider);
if (divider != null) {
@@ -116,8 +108,6 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
final View primaryAction = holder.itemView.findViewById(android.R.id.primary);
if (primaryAction != null) {
clickHandler = primaryAction;
// set the item view to disabled to remove any touch effects
holder.itemView.setEnabled(false);
}
clickHandler.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_SUGGESTION, id);
@@ -198,13 +188,12 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
? R.layout.suggestion_tile_remote_container
: R.layout.suggestion_tile;
} else {
return R.layout.suggestion_tile;
// TODO: Add remote view field in Suggestion, and enable this.
// Suggestion suggestion = getSuggestionsV2(position);
// return suggestion.remoteViews != null
// ? R.layout.suggestion_tile_remote_container
// : R.layout.suggestion_tile;
final Suggestion suggestion = getSuggestionsV2(position);
if ((suggestion.getFlags() & Suggestion.FLAG_HAS_BUTTON) != 0) {
return R.layout.suggestion_tile_with_button;
} else {
return R.layout.suggestion_tile;
}
}
}

View File

@@ -89,7 +89,7 @@ public class SuggestionDismissController extends ItemTouchHelper.SimpleCallback
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final int layoutId = viewHolder.getItemViewType();
if (layoutId == R.layout.suggestion_tile
|| layoutId == R.layout.suggestion_tile_remote_container) {
|| layoutId == R.layout.suggestion_tile_with_button) {
// Only return swipe direction for suggestion tiles. All other types are not swipeable.
return super.getSwipeDirs(recyclerView, viewHolder);
}

View File

@@ -24,6 +24,10 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
/**
* deprecated in favor of {@link BugReportPreferenceControllerV2}
*/
@Deprecated
public class BugReportPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin {

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2016 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.os.UserManager;
public class BugReportPreferenceControllerV2 extends DeveloperOptionsPreferenceController {
private static final String KEY_BUGREPORT = "bugreport";
private final UserManager mUserManager;
public BugReportPreferenceControllerV2(Context context) {
super(context);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
@Override
public boolean isAvailable() {
return !mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
}
@Override
public String getPreferenceKey() {
return KEY_BUGREPORT;
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
// intentional no-op
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
// intentional no-op
}
}

View File

@@ -23,4 +23,6 @@ public interface DevelopmentOptionsActivityRequestCodes {
int REQUEST_CODE_ENABLE_OEM_UNLOCK = 0;
int REQUEST_CODE_DEBUG_APP = 1;
int REQUEST_MOCK_LOCATION_APP = 2;
}

View File

@@ -245,14 +245,14 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
// take bug report
controllers.add(new BugReportPreferenceControllerV2(context));
controllers.add(new LocalBackupPasswordPreferenceController(context));
controllers.add(new StayAwakePreferenceController(context, lifecycle));
// hdcp checking
controllers.add(new HdcpCheckingPreferenceController(context));
controllers.add(new BluetoothSnoopLogPreferenceController(context));
controllers.add(new OemUnlockPreferenceController(context, activity, fragment));
// running services
// convert to file encryption
controllers.add(new FileEncryptionPreferenceController(context));
controllers.add(new PictureColorModePreferenceController(context, lifecycle));
controllers.add(new WebViewAppPreferenceControllerV2(context));
controllers.add(new CoolColorTemperaturePreferenceController(context));
@@ -263,7 +263,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new ClearAdbKeysPreferenceController(context, fragment));
controllers.add(new LocalTerminalPreferenceController(context));
controllers.add(new BugReportInPowerPreferenceControllerV2(context));
// select mock location app
controllers.add(new MockLocationAppPreferenceController(context, fragment));
controllers.add(new DebugViewAttributesPreferenceController(context));
controllers.add(new SelectDebugAppPreferenceController(context, fragment));
controllers.add(new WaitForDebuggerPreferenceController(context));
@@ -320,7 +320,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
// inactive apps
controllers.add(new AllowAppsOnExternalPreferenceController(context));
controllers.add(new ResizableActivityPreferenceController(context));
// reset shortcutmanager rate-limiting
controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
return controllers;
}

View File

@@ -0,0 +1,105 @@
/*
* 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.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.storage.IStorageManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.R;
public class FileEncryptionPreferenceController extends DeveloperOptionsPreferenceController {
private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
private static final String KEY_STORAGE_MANAGER = "mount";
@VisibleForTesting
static final String FILE_ENCRYPTION_PROPERTY_KEY = "ro.crypto.type";
private final IStorageManager mStorageManager;
private Preference mPreference;
public FileEncryptionPreferenceController(Context context) {
super(context);
mStorageManager = getStorageManager();
}
@Override
public boolean isAvailable() {
if (mStorageManager == null) {
return false;
}
try {
return mStorageManager.isConvertibleToFBE();
} catch (RemoteException e) {
return false;
}
}
@Override
public String getPreferenceKey() {
return KEY_CONVERT_FBE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public void updateState(Preference preference) {
if (!TextUtils.equals("file",
SystemProperties.get(FILE_ENCRYPTION_PROPERTY_KEY, "none" /* default */))) {
return;
}
mPreference.setEnabled(false);
mPreference.setSummary(
mContext.getResources().getString(R.string.convert_to_file_encryption_done));
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
// intentional no-op
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
// intentional no-op
}
private IStorageManager getStorageManager() {
try {
return IStorageManager.Stub.asInterface(
ServiceManager.getService(KEY_STORAGE_MANAGER));
} catch (VerifyError e) {
// Used for tests since Robolectric cannot initialize this class.
return null;
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.os.Build;
import android.os.SystemProperties;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settingslib.development.SystemPropPoker;
public class HdcpCheckingPreferenceController extends
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener {
private static final String HDCP_CHECKING_KEY = "hdcp_checking";
@VisibleForTesting
static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
@VisibleForTesting
static final String USER_BUILD_TYPE = "user";
private final String[] mListValues;
private final String[] mListSummaries;
private ListPreference mPreference;
public HdcpCheckingPreferenceController(Context context) {
super(context);
mListValues = mContext.getResources().getStringArray(R.array.hdcp_checking_values);
mListSummaries = mContext.getResources().getStringArray(R.array.hdcp_checking_summaries);
}
@Override
public boolean isAvailable() {
return !TextUtils.equals(USER_BUILD_TYPE, getBuildType());
}
@Override
public String getPreferenceKey() {
return HDCP_CHECKING_KEY;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (ListPreference) screen.findPreference(getPreferenceKey());
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
SystemProperties.set(HDCP_CHECKING_PROPERTY, newValue.toString());
updateHdcpValues();
SystemPropPoker.getInstance().poke();
return true;
}
@Override
public void updateState(Preference preference) {
updateHdcpValues();
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
mPreference.setEnabled(true);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
mPreference.setEnabled(false);
}
private void updateHdcpValues() {
final String currentValue = SystemProperties.get(HDCP_CHECKING_PROPERTY);
int index = 1; // Defaults to drm-only. Needs to match with R.array.hdcp_checking_values
for (int i = 0; i < mListValues.length; i++) {
if (TextUtils.equals(currentValue, mListValues[i])) {
index = i;
break;
}
}
mPreference.setValue(mListValues[index]);
mPreference.setSummary(mListSummaries[index]);
}
@VisibleForTesting
public String getBuildType() {
return Build.TYPE;
}
}

View File

@@ -0,0 +1,183 @@
/*
* 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_MOCK_LOCATION_APP;
import android.Manifest;
import android.app.Activity;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.settings.R;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.util.List;
public class MockLocationAppPreferenceController extends DeveloperOptionsPreferenceController {
private static final String MOCK_LOCATION_APP_KEY = "mock_location_app";
private static final int[] MOCK_LOCATION_APP_OPS = new int[]{AppOpsManager.OP_MOCK_LOCATION};
private final DevelopmentSettingsDashboardFragment mFragment;
private final AppOpsManager mAppsOpsManager;
private final PackageManagerWrapper mPackageManager;
private Preference mPreference;
public MockLocationAppPreferenceController(Context context,
DevelopmentSettingsDashboardFragment fragment) {
super(context);
mFragment = fragment;
mAppsOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = new PackageManagerWrapper(context.getPackageManager());
}
@Override
public String getPreferenceKey() {
return MOCK_LOCATION_APP_KEY;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
final Intent intent = new Intent(mContext, AppPicker.class);
intent.putExtra(AppPicker.EXTRA_REQUESTIING_PERMISSION,
Manifest.permission.ACCESS_MOCK_LOCATION);
mFragment.startActivityForResult(intent, REQUEST_MOCK_LOCATION_APP);
return true;
}
@Override
public void updateState(Preference preference) {
updateMockLocation();
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode != REQUEST_MOCK_LOCATION_APP || resultCode != Activity.RESULT_OK) {
return false;
}
writeMockLocation(data.getAction());
updateMockLocation();
return true;
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
mPreference.setEnabled(true);
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
mPreference.setEnabled(false);
}
private void updateMockLocation() {
final String mockLocationApp = getCurrentMockLocationApp();
if (!TextUtils.isEmpty(mockLocationApp)) {
mPreference.setSummary(
mContext.getResources().getString(R.string.mock_location_app_set,
getAppLabel(mockLocationApp)));
} else {
mPreference.setSummary(
mContext.getResources().getString(R.string.mock_location_app_not_set));
}
}
private void writeMockLocation(String mockLocationAppName) {
removeAllMockLocations();
// Enable the app op of the new mock location app if such.
if (!TextUtils.isEmpty(mockLocationAppName)) {
try {
final ApplicationInfo ai = mPackageManager.getApplicationInfo(
mockLocationAppName, PackageManager.MATCH_DISABLED_COMPONENTS);
mAppsOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
mockLocationAppName, AppOpsManager.MODE_ALLOWED);
} catch (PackageManager.NameNotFoundException e) {
/* ignore */
}
}
}
private String getAppLabel(String mockLocationApp) {
try {
final ApplicationInfo ai = mPackageManager.getApplicationInfo(
mockLocationApp, PackageManager.MATCH_DISABLED_COMPONENTS);
final CharSequence appLabel = mPackageManager.getApplicationLabel(ai);
return appLabel != null ? appLabel.toString() : mockLocationApp;
} catch (PackageManager.NameNotFoundException e) {
return mockLocationApp;
}
}
private void removeAllMockLocations() {
// Disable the app op of the previous mock location app if such.
final List<AppOpsManager.PackageOps> packageOps = mAppsOpsManager.getPackagesForOps(
MOCK_LOCATION_APP_OPS);
if (packageOps == null) {
return;
}
// Should be one but in case we are in a bad state due to use of command line tools.
for (AppOpsManager.PackageOps packageOp : packageOps) {
if (packageOp.getOps().get(0).getMode() != AppOpsManager.MODE_ERRORED) {
removeMockLocationForApp(packageOp.getPackageName());
}
}
}
private void removeMockLocationForApp(String appName) {
try {
final ApplicationInfo ai = mPackageManager.getApplicationInfo(
appName, PackageManager.MATCH_DISABLED_COMPONENTS);
mAppsOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
appName, AppOpsManager.MODE_ERRORED);
} catch (PackageManager.NameNotFoundException e) {
/* ignore */
}
}
private String getCurrentMockLocationApp() {
final List<AppOpsManager.PackageOps> packageOps = mAppsOpsManager.getPackagesForOps(
MOCK_LOCATION_APP_OPS);
if (packageOps != null) {
for (AppOpsManager.PackageOps packageOp : packageOps) {
if (packageOp.getOps().get(0).getMode() == AppOpsManager.MODE_ALLOWED) {
return packageOps.get(0).getPackageName();
}
}
}
return null;
}
}

View File

@@ -0,0 +1,91 @@
/*
* 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.content.pm.IShortcutService;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.android.settings.R;
public class ShortcutManagerThrottlingPreferenceController extends
DeveloperOptionsPreferenceController {
private static final String TAG = "ShortcutMgrPrefCtrl";
private static final String SHORTCUT_MANAGER_RESET_KEY = "reset_shortcut_manager_throttling";
private final IShortcutService mShortcutService;
public ShortcutManagerThrottlingPreferenceController(Context context) {
super(context);
mShortcutService = getShortCutService();
}
@Override
public String getPreferenceKey() {
return SHORTCUT_MANAGER_RESET_KEY;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(SHORTCUT_MANAGER_RESET_KEY, preference.getKey())) {
return false;
}
resetShortcutManagerThrottling();
return true;
}
@Override
protected void onDeveloperOptionsSwitchEnabled() {
// intentional no-op
}
@Override
protected void onDeveloperOptionsSwitchDisabled() {
// intentional no-op
}
private void resetShortcutManagerThrottling() {
if (mShortcutService == null) {
return;
}
try {
mShortcutService.resetThrottling();
Toast.makeText(mContext, R.string.reset_shortcut_manager_throttling_complete,
Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
Log.e(TAG, "Failed to reset rate limiting", e);
}
}
private IShortcutService getShortCutService() {
try {
return IShortcutService.Stub.asInterface(
ServiceManager.getService(Context.SHORTCUT_SERVICE));
} catch (VerifyError e) {
// Used for tests since Robolectric cannot initialize this class.
return null;
}
}
}

View File

@@ -0,0 +1,45 @@
/*
* 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.featureflags;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.util.FeatureFlagUtils;
public class FeatureFlagPreference extends SwitchPreference {
private final String mKey;
public FeatureFlagPreference(Context context, String key) {
super(context);
mKey = key;
setKey(key);
setTitle(key);
setCheckedInternal(FeatureFlagUtils.isEnabled(mKey));
}
@Override
public void setChecked(boolean isChecked) {
setCheckedInternal(isChecked);
FeatureFlagUtils.setEnabled(mKey, isChecked);
}
private void setCheckedInternal(boolean isChecked) {
super.setChecked(isChecked);
setSummary(Boolean.toString(isChecked));
}
}

View File

@@ -23,6 +23,7 @@ import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.List;
public class FeatureFlagsDashboard extends DashboardFragment {
@@ -51,6 +52,8 @@ public class FeatureFlagsDashboard extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new FeatureFlagsPreferenceController(context, getLifecycle()));
return controllers;
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.featureflags;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.FeatureFlagUtils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import java.util.Map;
public class FeatureFlagsPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnStart {
private PreferenceScreen mScreen;
public FeatureFlagsPreferenceController(Context context, Lifecycle lifecycle) {
super(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return null;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
}
@Override
public void onStart() {
if (mScreen == null) {
return;
}
final Map<String, String> featureMap = FeatureFlagUtils.getAllFeatureFlags();
if (featureMap == null) {
return;
}
mScreen.removeAll();
final Context prefContext = mScreen.getContext();
for (String prefixedFeature : featureMap.keySet()) {
if (prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_PREFIX)
&& !prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX)) {
final String feature = prefixedFeature.substring(
FeatureFlagUtils.FFLAG_PREFIX.length());
final Preference pref = new FeatureFlagPreference(prefContext, feature);
mScreen.addPreference(pref);
}
}
}
}

View File

@@ -18,47 +18,19 @@ package com.android.settings.deviceinfo;
import android.content.Context;
import android.os.Build;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.deviceinfo.AbstractSerialNumberPreferenceController;
public class SerialNumberPreferenceController extends AbstractPreferenceController implements
/**
* Preference controller for displaying device serial number. Wraps {@link Build#getSerial()}.
*/
public class SerialNumberPreferenceController extends
AbstractSerialNumberPreferenceController implements
PreferenceControllerMixin {
private static final String KEY_SERIAL_NUMBER = "serial_number";
private final String mSerialNumber;
public SerialNumberPreferenceController(Context context) {
this(context, Build.getSerial());
}
@VisibleForTesting
SerialNumberPreferenceController(Context context, String serialNumber) {
super(context);
mSerialNumber = serialNumber;
}
@Override
public boolean isAvailable() {
return !TextUtils.isEmpty(mSerialNumber);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final Preference pref = screen.findPreference(KEY_SERIAL_NUMBER);
if (pref != null) {
pref.setSummary(mSerialNumber);
}
}
@Override
public String getPreferenceKey() {
return KEY_SERIAL_NUMBER;
}
// This space intentionally left blank
}

View File

@@ -35,15 +35,13 @@ import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.SettingsStringUtil;
import android.util.Slog;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
import com.android.settings.core.TouchOverlayManager;
/** @hide */
public class NotificationAccessConfirmationActivity extends Activity
@@ -54,14 +52,12 @@ public class NotificationAccessConfirmationActivity extends Activity
private int mUserId;
private ComponentName mComponentName;
private TouchOverlayManager mTouchOverlayManager;
private NotificationManager mNm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTouchOverlayManager = new TouchOverlayManager(this);
mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME);
@@ -87,6 +83,20 @@ public class NotificationAccessConfirmationActivity extends Activity
getWindow().setCloseOnTouchOutside(false);
}
@Override
public void onResume() {
super.onResume();
getWindow().addFlags(
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
}
@Override
public void onPause() {
getWindow().clearFlags(
WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
super.onPause();
}
private void onAllow() {
String requiredPermission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
try {
@@ -130,16 +140,4 @@ public class NotificationAccessConfirmationActivity extends Activity
finish();
}
}
@Override
protected void onResume() {
super.onResume();
mTouchOverlayManager.setOverlayAllowed(false);
}
@Override
protected void onPause() {
super.onPause();
mTouchOverlayManager.setOverlayAllowed(true);
}
}

View File

@@ -47,8 +47,8 @@ public class SupportDashboardActivity extends Activity implements Indexable {
supportFeatureProvider.startSupportV2(this);
} else {
startActivity(new Intent(this, LegacySupportActivity.class));
finish();
}
finish();
}
/**

View File

@@ -18,15 +18,17 @@ package android.service.settings.suggestions;
import android.app.PendingIntent;
import android.graphics.drawable.Icon;
import android.os.Parcel;
import android.text.TextUtils;
import android.widget.RemoteViews;
public class Suggestion {
public static final int FLAG_HAS_BUTTON = 1 << 0;
private final String mId;
private final CharSequence mTitle;
private final CharSequence mSummary;
private final Icon mIcon;
private final int mFlags;
private final PendingIntent mPendingIntent;
/**
@@ -57,6 +59,10 @@ public class Suggestion {
return mIcon;
}
public int getFlags() {
return mFlags;
}
/**
* The Intent to launch when the suggestion is activated.
*/
@@ -70,13 +76,16 @@ public class Suggestion {
mIcon = builder.mIcon;
mPendingIntent = builder.mPendingIntent;
mId = builder.mId;
mFlags = builder.mFlags;
}
/**
* Builder class for {@link Suggestion}.
*/
public static class Builder {
private final String mId;
private int mFlags;
private CharSequence mTitle;
private CharSequence mSummary;
private Icon mIcon;
@@ -114,6 +123,11 @@ public class Suggestion {
return this;
}
public Builder setFlags(int flags) {
mFlags = flags;
return this;
}
/**
* Sets suggestion intent
*/

View File

@@ -19,6 +19,9 @@ package android.util;
import android.os.SystemProperties;
import android.text.TextUtils;
import java.util.HashMap;
import java.util.Map;
/**
* This class is only needed to get around Robolectric issue.
*/
@@ -43,4 +46,19 @@ public class FeatureFlagUtils {
value = SystemProperties.get(FFLAG_PREFIX + feature);
return Boolean.parseBoolean(value);
}
/**
* Override feature flag to new state.
*/
public static void setEnabled(String feature, boolean enabled) {
SystemProperties.set(FFLAG_OVERRIDE_PREFIX + feature, enabled ? "true" : "false");
}
public static Map<String, String> getAllFeatureFlags() {
final Map<String, String> features = new HashMap<>();
features.put(FFLAG_PREFIX + "abc", "false");
features.put(FFLAG_OVERRIDE_PREFIX + "abc", "true");
return features;
}
}

View File

@@ -19,52 +19,59 @@ package com.android.settings.applications;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.app.Activity;
import android.content.Context;
import android.view.Window;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.core.TouchOverlayManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowPreferenceFragment;
import com.android.settings.testutils.shadow.ShadowAppInfoBase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DrawOverlayDetailsTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private DrawOverlayDetails mFragment;
private Activity mActivity;
@Mock
private TouchOverlayManager mTouchOverlayManager;
private Window mWindow;
private FakeFeatureFactory mFeatureFactory;
@Spy
private DrawOverlayDetails mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest(mContext);
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mFragment = new DrawOverlayDetails();
ReflectionHelpers.setField(mFragment, "mTouchOverlayManager", mTouchOverlayManager);
FakeFeatureFactory.setupForTest(mActivity);
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mActivity);
}
@Test
public void logSpecialPermissionChange() {
mFragment.onAttach(ShadowApplication.getInstance().getApplicationContext());
when(mFragment.getContext()).thenReturn(
ShadowApplication.getInstance().getApplicationContext());
mFragment.logSpecialPermissionChange(true, "app");
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.APP_SPECIAL_PERMISSION_APPDRAW_ALLOW), eq("app"));
@@ -75,16 +82,17 @@ public class DrawOverlayDetailsTest {
}
@Test
@Config(shadows = ShadowPreferenceFragment.class)
public void onStart_disableOverlay() {
mFragment.onStart();
verify(mTouchOverlayManager).setOverlayAllowed(false);
}
@Config(shadows = {ShadowAppInfoBase.class})
public void hideNonSystemOverlaysWhenResumed() {
when(mFragment.getActivity()).thenReturn(mActivity);
when(mActivity.getWindow()).thenReturn(mWindow);
@Test
@Config(shadows = ShadowPreferenceFragment.class)
public void onStop_enableOverlay() {
mFragment.onStop();
verify(mTouchOverlayManager).setOverlayAllowed(true);
mFragment.onResume();
mFragment.onPause();
InOrder inOrder = Mockito.inOrder(mWindow);
inOrder.verify(mWindow).addFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
inOrder.verify(mWindow).clearFlags(PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
inOrder.verifyNoMoreInteractions();
}
}

View File

@@ -143,6 +143,21 @@ public class SuggestionAdapterTest {
.isEqualTo(R.layout.suggestion_tile);
}
@Test
public void getItemType_hasButton_shouldReturnSuggestionWithButton() {
final List<Suggestion> suggestions = new ArrayList<>();
suggestions.add(new Suggestion.Builder("id")
.setFlags(Suggestion.FLAG_HAS_BUTTON)
.setTitle("123")
.setSummary("456")
.build());
mSuggestionAdapter = new SuggestionAdapter(mContext, null /* suggestions */,
suggestions, new ArrayList<>());
assertThat(mSuggestionAdapter.getItemViewType(0))
.isEqualTo(R.layout.suggestion_tile_with_button);
}
@Test
public void onBindViewHolder_shouldSetListener() {
final View view = spy(LayoutInflater.from(mContext).inflate(

View File

@@ -92,7 +92,7 @@ public class SuggestionDismissControllerTest {
@Test
public void getSwipeDirs_isSuggestionTileCard_shouldReturnDirection() {
final RecyclerView.ViewHolder vh = mock(RecyclerView.ViewHolder.class);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile_remote_container);
when(vh.getItemViewType()).thenReturn(R.layout.suggestion_tile_with_button);
assertThat(mController.getSwipeDirs(mRecyclerView, vh))
.isEqualTo(ItemTouchHelper.START | ItemTouchHelper.END);

View File

@@ -39,6 +39,10 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* deprecated in favor of {@link BugReportPreferenceControllerV2}
*/
@Deprecated
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BugReportPreferenceControllerTest {

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2016 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.Matchers.anyString;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.UserManager;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
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 BugReportPreferenceControllerV2Test {
@Mock
private Context mContext;
@Mock
private UserManager mUserManager;
private BugReportPreferenceControllerV2 mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = new BugReportPreferenceControllerV2(mContext);
}
@Test
public void isAvailable_hasDebugRestriction_shouldBeFalse() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(true);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_noDebugRestriction_shouldBeTrue() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
assertThat(mController.isAvailable()).isTrue();
}
}

View File

@@ -0,0 +1,134 @@
/*
* 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.FileEncryptionPreferenceController
.FILE_ENCRYPTION_PROPERTY_KEY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.storage.IStorageManager;
import android.support.v7.preference.Preference;
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.settings.testutils.shadow.SettingsShadowSystemProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {SettingsShadowSystemProperties.class})
public class FileEncryptionPreferenceControllerTest {
@Mock
private Preference mPreference;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private IStorageManager mStorageManager;
private Context mContext;
private FileEncryptionPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new FileEncryptionPreferenceController(mContext);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mPreference);
}
@After
public void teardown() {
SettingsShadowSystemProperties.clear();
}
@Test
public void isAvailable_storageManagerNull_shouldBeFalse() {
ReflectionHelpers.setField(mController, "mStorageManager", null);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_notConvertibleToFBE_shouldBeFalse() throws RemoteException {
ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
when(mStorageManager.isConvertibleToFBE()).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_convertibleToFBE_shouldBeTrue() throws RemoteException {
ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void updateState_settingIsNotFile_shouldDoNothing() throws RemoteException {
ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
mController.displayPreference(mPreferenceScreen);
SystemProperties.set(FILE_ENCRYPTION_PROPERTY_KEY, "foobar");
mController.updateState(mPreference);
verify(mPreference, never()).setEnabled(anyBoolean());
verify(mPreference, never()).setSummary(anyString());
}
@Test
public void updateState_settingIsFile_shouldSetSummaryAndDisablePreference()
throws RemoteException {
ReflectionHelpers.setField(mController, "mStorageManager", mStorageManager);
when(mStorageManager.isConvertibleToFBE()).thenReturn(true);
mController.displayPreference(mPreferenceScreen);
SystemProperties.set(FILE_ENCRYPTION_PROPERTY_KEY, "file");
mController.updateState(mPreference);
verify(mPreference).setEnabled(false);
verify(mPreference).setSummary(
mContext.getResources().getString(R.string.convert_to_file_encryption_done));
}
}

View File

@@ -0,0 +1,164 @@
/*
* 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.HdcpCheckingPreferenceController
.HDCP_CHECKING_PROPERTY;
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.os.SystemProperties;
import android.support.v7.preference.ListPreference;
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.settings.testutils.shadow.SettingsShadowSystemProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
shadows = {SettingsShadowSystemProperties.class})
public class HdcpCheckingPreferenceControllerTest {
private static final String USER_DEBUG = "userdebug";
@Mock
private ListPreference mPreference;
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private HdcpCheckingPreferenceController mController;
/**
* Array Values Key
*
* 0: Never Check
* 1: Check for DRM content only
* 2: Always Check
*/
private String[] mValues;
private String[] mSummaries;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mValues = mContext.getResources().getStringArray(R.array.hdcp_checking_values);
mSummaries = mContext.getResources().getStringArray(R.array.hdcp_checking_summaries);
mController = new HdcpCheckingPreferenceController(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
}
@After
public void teardown() {
SettingsShadowSystemProperties.clear();
}
@Test
public void isAvailable_isUserBuildType_shouldReturnFalse() {
mController = spy(mController);
doReturn(HdcpCheckingPreferenceController.USER_BUILD_TYPE).when(mController).getBuildType();
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_isUserDebugBuildType_shouldReturnTrue() {
mController = spy(mController);
doReturn(USER_DEBUG).when(mController).getBuildType();
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void onPreferenceChange_setNeverCheckHdcp_shouldEnableNeverCheckHdcp() {
mController.onPreferenceChange(mPreference, mValues[0]);
assertThat(SystemProperties.get(HDCP_CHECKING_PROPERTY)).isEqualTo(mValues[0]);
}
@Test
public void onPreferenceChange_setCheckDrm_shouldEnableCheckDrm() {
mController.onPreferenceChange(mPreference, mValues[1]);
assertThat(SystemProperties.get(HDCP_CHECKING_PROPERTY)).isEqualTo(mValues[1]);
}
@Test
public void updateState_neverCheckHdcp_shouldEnableNeverCheckHdcp() {
SystemProperties.set(HDCP_CHECKING_PROPERTY, mValues[0]);
mController.updateState(mPreference);
verify(mPreference).setValue(mValues[0]);
verify(mPreference).setSummary(mSummaries[0]);
}
@Test
public void updateState_checkDrm_shouldEnableCheckDrm() {
SystemProperties.set(HDCP_CHECKING_PROPERTY, mValues[1]);
mController.updateState(mPreference);
verify(mPreference).setValue(mValues[1]);
verify(mPreference).setSummary(mSummaries[1]);
}
@Test
public void updateState_noValueSet_shouldEnableCheckDrmAsDefault() {
SystemProperties.set(HDCP_CHECKING_PROPERTY, null);
mController.updateState(mPreference);
verify(mPreference).setValue(mValues[1]);
verify(mPreference).setSummary(mSummaries[1]);
}
@Test
public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsSwitchDisabled();
verify(mPreference).setEnabled(false);
}
@Test
public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() {
mController.onDeveloperOptionsSwitchEnabled();
verify(mPreference).setEnabled(true);
}
}

View File

@@ -0,0 +1,166 @@
package com.android.settings.development;
import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes
.REQUEST_MOCK_LOCATION_APP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
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.wrapper.PackageManagerWrapper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
import java.util.Collections;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class MockLocationAppPreferenceControllerTest {
@Mock
private DevelopmentSettingsDashboardFragment mFragment;
@Mock
private AppOpsManager mAppOpsManager;
@Mock
private PackageManagerWrapper mPackageManager;
@Mock
private Preference mPreference;
@Mock
private PreferenceScreen mScreen;
@Mock
private AppOpsManager.PackageOps mPackageOps;
@Mock
private AppOpsManager.OpEntry mOpEntry;
@Mock
private ApplicationInfo mApplicationInfo;
private Context mContext;
private MockLocationAppPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = spy(new MockLocationAppPreferenceController(mContext, mFragment));
ReflectionHelpers.setField(mController, "mAppsOpsManager", mAppOpsManager);
ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
}
@Test
public void updateState_foobarAppSelected_shouldSetSummaryToFoobar() {
final String appName = "foobar";
when(mAppOpsManager.getPackagesForOps(any())).thenReturn(
Collections.singletonList(mPackageOps));
when(mPackageOps.getOps()).thenReturn(Collections.singletonList(mOpEntry));
when(mOpEntry.getMode()).thenReturn(AppOpsManager.MODE_ALLOWED);
when(mPackageOps.getPackageName()).thenReturn(appName);
mController.updateState(mPreference);
verify(mPreference).setSummary(
mContext.getResources().getString(R.string.mock_location_app_set, appName));
}
@Test
public void updateState_noAppSelected_shouldSetSummaryToDefault() {
when(mAppOpsManager.getPackagesForOps(any())).thenReturn(
Collections.emptyList());
mController.updateState(mPreference);
verify(mPreference).setSummary(
mContext.getResources().getString(R.string.mock_location_app_not_set));
}
@Test
public void onActivityResult_fooPrevAppBarNewApp_shouldRemoveFooAndSetBarAsMockLocationApp()
throws PackageManager.NameNotFoundException {
final String prevAppName = "foo";
final String newAppName = "bar";
final Intent intent = new Intent();
intent.setAction(newAppName);
when(mAppOpsManager.getPackagesForOps(any())).thenReturn(
Collections.singletonList(mPackageOps));
when(mPackageOps.getOps()).thenReturn(Collections.singletonList(mOpEntry));
when(mOpEntry.getMode()).thenReturn(AppOpsManager.MODE_ALLOWED);
when(mPackageOps.getPackageName()).thenReturn(prevAppName);
when(mPackageManager.getApplicationInfo(anyString(),
eq(PackageManager.MATCH_DISABLED_COMPONENTS))).thenReturn(mApplicationInfo);
final boolean handled = mController.onActivityResult(REQUEST_MOCK_LOCATION_APP,
Activity.RESULT_OK, intent);
assertThat(handled).isTrue();
verify(mAppOpsManager).setMode(anyInt(), anyInt(), eq(newAppName),
eq(AppOpsManager.MODE_ALLOWED));
verify(mAppOpsManager).setMode(anyInt(), anyInt(), eq(prevAppName),
eq(AppOpsManager.MODE_ERRORED));
}
@Test
public void onActivityResult_incorrectCode_shouldReturnFalse() {
final boolean handled = mController.onActivityResult(30983150 /* request code */,
Activity.RESULT_OK, null /* intent */);
assertThat(handled).isFalse();
}
@Test
public void handlePreferenceTreeClick_samePreferenceKey_shouldLaunchActivity() {
final String preferenceKey = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(preferenceKey);
final boolean handled = mController.handlePreferenceTreeClick(mPreference);
assertThat(handled).isTrue();
verify(mFragment).startActivityForResult(any(), eq(REQUEST_MOCK_LOCATION_APP));
}
@Test
public void handlePreferenceTreeClick_incorrectPreferenceKey_shouldReturnFalse() {
when(mPreference.getKey()).thenReturn("SomeRandomKey");
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
}
@Test
public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsSwitchDisabled();
verify(mPreference).setEnabled(false);
}
@Test
public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() {
mController.onDeveloperOptionsSwitchEnabled();
verify(mPreference).setEnabled(true);
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.IShortcutService;
import android.os.RemoteException;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ShortcutManagerThrottlingPreferenceControllerTest {
@Mock
private SwitchPreference mPreference;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private IShortcutService mShortcutService;
private Context mContext;
private ShortcutManagerThrottlingPreferenceController mController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new ShortcutManagerThrottlingPreferenceController(mContext);
ReflectionHelpers.setField(mController, "mShortcutService", mShortcutService);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mPreference);
mController.displayPreference(mPreferenceScreen);
}
@Test
public void handlePreferenceTreeClick_differentPreferenceKey_shouldReturnFalse() {
when(mPreference.getKey()).thenReturn("SomeRandomKey");
assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
}
@Test
public void handlePreferenceTreeClick_correctPreferenceKey_shouldResetThrottling()
throws RemoteException {
when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
final boolean handled = mController.handlePreferenceTreeClick(mPreference);
assertThat(handled).isTrue();
verify(mShortcutService).resetThrottling();
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.featureflags;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v7.preference.PreferenceScreen;
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.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FeatureFlagPreferenceControllerTest {
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private Lifecycle mLifecycle;
private FeatureFlagsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mLifecycle = new Lifecycle();
mController = new FeatureFlagsPreferenceController(mContext, mLifecycle);
when(mScreen.getContext()).thenReturn(mContext);
mController.displayPreference(mScreen);
}
@Test
public void verifyConstants() {
assertThat(mController.isAvailable()).isTrue();
assertThat(mController.getPreferenceKey()).isNull();
}
@Test
public void onStart_shouldRefreshFeatureFlags() {
mLifecycle.onStart();
verify(mScreen).removeAll();
verify(mScreen).addPreference(any(FeatureFlagPreference.class));
}
}

View File

@@ -0,0 +1,61 @@
/*
* 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.featureflags;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FeatureFlagPreferenceTest {
private static final String KEY = "feature_key";
private Context mContext;
private FeatureFlagPreference mPreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mPreference = new FeatureFlagPreference(mContext, KEY);
}
@Test
public void constructor_shouldSetTitleAndSummary() {
assertThat(mPreference.getTitle()).isEqualTo(KEY);
assertThat(mPreference.getSummary()).isEqualTo("false");
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void toggle_shouldUpdateSummary() {
mPreference.setChecked(true);
assertThat(mPreference.getSummary()).isEqualTo("true");
assertThat(mPreference.isChecked()).isTrue();
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2016 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.deviceinfo;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
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 SerialNumberPreferenceControllerTest {
@Mock(answer = RETURNS_DEEP_STUBS)
private Context mContext;
@Mock(answer = RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
private SerialNumberPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testIsAvaiable_noSerial_shouldReturnFalse() {
mController = new SerialNumberPreferenceController(mContext, null);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void testIsAvaiable_hasSerial_shouldReturnTrue() {
mController = new SerialNumberPreferenceController(mContext, "123");
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void testDisplay_noSerial_shouldHidePreference() {
final Preference preference = mock(Preference.class);
when(mScreen.getPreferenceCount()).thenReturn(1);
when(mScreen.getPreference(0)).thenReturn(preference);
mController = new SerialNumberPreferenceController(mContext, null);
when(preference.getKey()).thenReturn(mController.getPreferenceKey());
mController.displayPreference(mScreen);
verify(mScreen).removePreference(any(Preference.class));
}
@Test
public void testDisplay_hasSerial_shouldSummary() {
final String serial = "123";
final Preference preference = mock(Preference.class);
when(mScreen.findPreference(anyString())).thenReturn(preference);
mController = new SerialNumberPreferenceController(mContext, serial);
mController.displayPreference(mScreen);
verify(mScreen, never()).removePreference(any(Preference.class));
verify(preference).setSummary(serial);
}
}

View File

@@ -16,20 +16,20 @@
package com.android.settings.testutils.shadow;
import android.support.v14.preference.PreferenceFragment;
import com.android.settings.applications.AppInfoBase;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(PreferenceFragment.class)
public class ShadowPreferenceFragment {
@Implements(AppInfoBase.class)
public class ShadowAppInfoBase {
@Implementation
public void onStart() {
public void onResume() {
// No-op.
}
@Implementation
public void onStop() {
public void onPause() {
// No-op.
}
}