Snap for 4842501 from f350fa875b to qt-release

Change-Id: Ic753ba0535be15974d9a5aad119027b5e30878e3
This commit is contained in:
android-build-team Robot
2018-06-15 09:31:53 +00:00
73 changed files with 947 additions and 1366 deletions

View File

@@ -2362,7 +2362,6 @@
android:name="Settings$DataUsageSummaryActivity"
android:label="@string/data_usage_summary_title"
android:icon="@drawable/ic_settings_data_usage"
android:enabled="false"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">

View File

@@ -31,6 +31,7 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="56dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<TextView

View File

@@ -17,4 +17,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="32dp"
android:numColumns="3"
android:gravity="center"
android:importantForAccessibility="noHideDescendants" />

View File

@@ -14,33 +14,28 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAccessibility="noHideDescendants">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingTop="8dp">
<LinearLayout
android:layout_width="@dimen/screen_zoom_preview_app_icon_width"
<ImageView
android:id="@android:id/icon1"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginBottom="4dp"
android:scaleType="fitCenter" />
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="8dp">
<ImageView
android:id="@android:id/icon1"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginBottom="4dp"
android:scaleType="fitCenter" />
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_horizontal|top"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Caption" />
</LinearLayout>
</FrameLayout>
android:ellipsize="end"
android:gravity="center_horizontal|top"
android:singleLine="true"
android:textAppearance="@android:style/TextAppearance.Material.Caption" />
</LinearLayout>

View File

@@ -80,8 +80,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:layoutDirection="ltr">
android:orientation="horizontal">
<include android:id="@+id/label_start"
layout="@layout/usage_side_label" />

View File

@@ -251,7 +251,6 @@
<dimen name="unmount_button_padding">8dp</dimen>
<!-- Display, Screen zoom -->
<dimen name="screen_zoom_preview_app_icon_width">88dp</dimen>
<dimen name="conversation_message_list_padding">10dp</dimen>
<dimen name="conversation_message_contact_icon_text_size">32sp</dimen>
<dimen name="conversation_message_text_size">16sp</dimen>

View File

@@ -289,7 +289,7 @@
<string name="bluetooth_notif_message">Tap to pair with <xliff:g id="device_name">%1$s</xliff:g>.</string>
<!-- Item in bluetooth settings screen, used to show the list of received files [CHAR LIMIT=30] -->
<string name="bluetooth_show_received_files">Received files</string>
<!-- Item in bluetooth settings screen, used to show the list of Files received via Bluetooth [CHAR LIMIT=30] -->
<!-- Item in bluetooth settings screen, used to show the list of Files received via Bluetooth [CHAR LIMIT=NONE] -->
<string name="bluetooth_show_files_received_via_bluetooth">Files received via Bluetooth</string>
<!-- Strings for BluetoothDevicePicker [CHAR LIMIT=40]-->
@@ -6999,6 +6999,9 @@
<string name="keywords_model_and_hardware">serial number, hardware version</string>
<string name="keywords_android_version">android security patch level, baseband version, kernel version</string>
<!-- Search keyword for Device Theme Settings [CHAR LIMIT=NONE] -->
<string name="keywords_systemui_theme">dark theme</string>
<!-- Search keyword for Send Device Feedback Setting [CHAR LIMIT=NONE] -->
<string name="keywords_device_feedback">bug</string>

View File

@@ -69,7 +69,7 @@
<Preference
android:key="special_access"
android:fragment="com.android.settings.applications.SpecialAccessSettings"
android:fragment="com.android.settings.applications.specialaccess.SpecialAccessSettings"
android:title="@string/special_access"
android:order="20" />

View File

@@ -29,8 +29,8 @@
<com.android.settings.widget.SeekBarPreference
android:key="battery_saver_seek_bar"
android:title="@string/battery_saver_seekbar_title_placeholder"
android:max="75"
android:min="5" />
android:max="15"
android:min="1" />
<com.android.settings.widget.TwoStateButtonPreference
android:key="battery_saver"

View File

@@ -141,7 +141,8 @@
android:title="@string/device_theme"
android:entries="@array/systemui_theme_entries"
android:entryValues="@array/systemui_theme_values"
settings:controller="com.android.settings.display.SystemUiThemePreferenceController" />
settings:controller="com.android.settings.display.SystemUiThemePreferenceController"
settings:keywords="@string/keywords_systemui_theme" />
<Preference
android:key="vr_display_pref"

View File

@@ -15,16 +15,17 @@
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="special_app_access_screen"
android:title="@string/special_access">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="special_app_access_screen"
android:title="@string/special_access">
<Preference
android:key="high_power_apps"
android:title="@string/high_power_apps"
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
settings:keywords="@string/keywords_ignore_optimizations">
settings:keywords="@string/keywords_ignore_optimizations"
settings:controller="com.android.settings.applications.specialaccess.HighPowerAppsController">
<extra
android:name="classname"
android:value="com.android.settings.Settings$HighPowerApplicationsActivity" />
@@ -33,7 +34,8 @@
<Preference
android:key="device_administrators"
android:title="@string/manage_device_admin"
android:fragment="com.android.settings.DeviceAdminSettings" />
android:fragment="com.android.settings.DeviceAdminSettings"
settings:controller="com.android.settings.applications.specialaccess.DeviceAdministratorsController" />
<Preference
android:key="system_alert_window"
@@ -48,7 +50,8 @@
<Preference
android:key="zen_access"
android:title="@string/manage_zen_access_title"
android:fragment="com.android.settings.notification.ZenAccessSettings" />
android:fragment="com.android.settings.notification.ZenAccessSettings"
settings:controller="com.android.settings.applications.specialaccess.ZenAccessController" />
<Preference
android:key="write_settings_apps"
@@ -63,23 +66,27 @@
<Preference
android:key="notification_access"
android:title="@string/manage_notification_access_title"
android:fragment="com.android.settings.notification.NotificationAccessSettings" />
android:fragment="com.android.settings.notification.NotificationAccessSettings"
settings:controller="com.android.settings.applications.specialaccess.NotificationAccessController" />
<Preference
android:key="picture_in_picture"
android:title="@string/picture_in_picture_title"
android:fragment="com.android.settings.applications.appinfo.PictureInPictureSettings"
settings:keywords="@string/picture_in_picture_keywords" />
settings:keywords="@string/picture_in_picture_keywords"
settings:controller="com.android.settings.applications.specialaccess.PictureInPictureController" />
<Preference
android:key="premium_sms"
android:title="@string/premium_sms_access"
android:fragment="com.android.settings.applications.PremiumSmsAccess" />
android:fragment="com.android.settings.applications.PremiumSmsAccess"
settings:controller="com.android.settings.applications.specialaccess.PremiumSmsController" />
<Preference
android:key="data_saver"
android:title="@string/unrestricted_data_saver"
android:fragment="com.android.settings.datausage.UnrestrictedDataAccess" />
android:fragment="com.android.settings.datausage.UnrestrictedDataAccess"
settings:controller="com.android.settings.applications.specialaccess.DataSaverController" />
<Preference
android:key="manage_external_sources"
@@ -105,7 +112,8 @@
android:key="enabled_vr_listeners"
android:title="@string/vr_listeners_title"
android:fragment="com.android.settings.applications.VrListenerSettings"
settings:keywords="@string/keywords_vr_listener">
settings:keywords="@string/keywords_vr_listener"
settings:controller="com.android.settings.applications.specialaccess.EnabledVrListenersController">
<extra
android:name="classname"
android:value="com.android.settings.Settings$VrListenersSettingsActivity" />

View File

@@ -1,106 +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.applications;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import android.provider.SearchIndexableResource;
import androidx.preference.Preference;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable
public class SpecialAccessSettings extends DashboardFragment {
private static final String TAG = "SpecialAccessSettings";
private static final String[] DISABLED_FEATURES_LOW_RAM =
new String[]{"notification_access", "zen_access", "enabled_vr_listeners",
"picture_in_picture"};
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.special_access;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
if (ActivityManager.isLowRamDeviceStatic()) {
for (String disabledFeature : DISABLED_FEATURES_LOW_RAM) {
Preference pref = findPreference(disabledFeature);
if (pref != null) {
removePreference(disabledFeature);
}
}
}
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(
@NonNull Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new HighPowerAppsController(context));
controllers.add(new DeviceAdministratorsController(context));
controllers.add(new PremiumSmsController(context));
controllers.add(new DataSaverController(context));
controllers.add(new EnabledVrListenersController(context));
return controllers;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SPECIAL_ACCESS;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.special_access;
result.add(sir);
return result;
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context);
}
};
}

View File

@@ -1,321 +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.applications.appinfo;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import android.util.Log;
import android.webkit.IWebViewUpdateService;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class AppActionButtonPreferenceController extends BasePreferenceController
implements AppInfoDashboardFragment.Callback {
private static final String TAG = "AppActionButtonControl";
private static final String KEY_ACTION_BUTTONS = "action_buttons";
@VisibleForTesting
ActionButtonPreference mActionButtons;
private final AppInfoDashboardFragment mParent;
private final String mPackageName;
private final HashSet<String> mHomePackages = new HashSet<>();
private final ApplicationFeatureProvider mApplicationFeatureProvider;
private int mUserId;
private DevicePolicyManager mDpm;
private UserManager mUserManager;
private PackageManager mPm;
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final boolean enabled = getResultCode() != Activity.RESULT_CANCELED;
Log.d(TAG, "Got broadcast response: Restart status for "
+ mParent.getAppEntry().info.packageName + " " + enabled);
updateForceStopButton(enabled);
}
};
public AppActionButtonPreferenceController(Context context, AppInfoDashboardFragment parent,
String packageName) {
super(context, KEY_ACTION_BUTTONS);
mParent = parent;
mPackageName = packageName;
mUserId = UserHandle.myUserId();
mApplicationFeatureProvider = FeatureFactory.getFactory(context)
.getApplicationFeatureProvider(context);
}
@Override
public int getAvailabilityStatus() {
return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
? DISABLED_FOR_USER : AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mActionButtons = ((ActionButtonPreference) screen.findPreference(KEY_ACTION_BUTTONS))
.setButton2Text(R.string.force_stop)
.setButton2Positive(false)
.setButton2Enabled(false);
}
@Override
public void refreshUi() {
if (mPm == null) {
mPm = mContext.getPackageManager();
}
if (mDpm == null) {
mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
}
if (mUserManager == null) {
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
final AppEntry appEntry = mParent.getAppEntry();
final PackageInfo packageInfo = mParent.getPackageInfo();
// Get list of "home" apps and trace through any meta-data references
final List<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
mPm.getHomeActivities(homeActivities);
mHomePackages.clear();
for (int i = 0; i < homeActivities.size(); i++) {
final ResolveInfo ri = homeActivities.get(i);
final String activityPkg = ri.activityInfo.packageName;
mHomePackages.add(activityPkg);
// Also make sure to include anything proxying for the home app
final Bundle metadata = ri.activityInfo.metaData;
if (metadata != null) {
final String metaPkg = metadata.getString(ActivityManager.META_HOME_ALTERNATE);
if (signaturesMatch(metaPkg, activityPkg)) {
mHomePackages.add(metaPkg);
}
}
}
checkForceStop(appEntry, packageInfo);
initUninstallButtons(appEntry, packageInfo);
}
@VisibleForTesting
void initUninstallButtons(AppEntry appEntry, PackageInfo packageInfo) {
final boolean isBundled = (appEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
boolean enabled;
if (isBundled) {
enabled = handleDisableable(appEntry, packageInfo);
} else {
enabled = initUninstallButtonForUserApp();
}
// If this is a device admin, it can't be uninstalled or disabled.
// We do this here so the text of the button is still set correctly.
if (isBundled && mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
enabled = false;
}
// We don't allow uninstalling DO/PO on *any* users, because if it's a system app,
// "uninstall" is actually "downgrade to the system version + disable", and "downgrade"
// will clear data on all users.
if (Utils.isProfileOrDeviceOwner(mUserManager, mDpm, packageInfo.packageName)) {
enabled = false;
}
// Don't allow uninstalling the device provisioning package.
if (Utils.isDeviceProvisioningPackage(mContext.getResources(), appEntry.info.packageName)) {
enabled = false;
}
// If the uninstall intent is already queued, disable the uninstall button
if (mDpm.isUninstallInQueue(mPackageName)) {
enabled = false;
}
// Home apps need special handling. Bundled ones we don't risk downgrading
// because that can interfere with home-key resolution. Furthermore, we
// can't allow uninstallation of the only home app, and we don't want to
// allow uninstallation of an explicitly preferred one -- the user can go
// to Home settings and pick a different one, after which we'll permit
// uninstallation of the now-not-default one.
if (enabled && mHomePackages.contains(packageInfo.packageName)) {
if (isBundled) {
enabled = false;
} else {
ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities);
if (currentDefaultHome == null) {
// No preferred default, so permit uninstall only when
// there is more than one candidate
enabled = (mHomePackages.size() > 1);
} else {
// There is an explicit default home app -- forbid uninstall of
// that one, but permit it for installed-but-inactive ones.
enabled = !packageInfo.packageName.equals(currentDefaultHome.getPackageName());
}
}
}
if (RestrictedLockUtils.hasBaseUserRestriction(
mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId)) {
enabled = false;
}
try {
final IWebViewUpdateService webviewUpdateService =
IWebViewUpdateService.Stub.asInterface(
ServiceManager.getService("webviewupdate"));
if (webviewUpdateService.isFallbackPackage(appEntry.info.packageName)) {
enabled = false;
}
} catch (RemoteException e) {
throw new RuntimeException(e);
}
mActionButtons.setButton1Enabled(enabled);
if (enabled) {
// Register listener
mActionButtons.setButton1OnClickListener(v -> mParent.handleUninstallButtonClick());
}
}
@VisibleForTesting
boolean initUninstallButtonForUserApp() {
boolean enabled = true;
final PackageInfo packageInfo = mParent.getPackageInfo();
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) == 0
&& mUserManager.getUsers().size() >= 2) {
// When we have multiple users, there is a separate menu
// to uninstall for all users.
enabled = false;
} else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
enabled = false;
mActionButtons.setButton1Visible(false);
}
mActionButtons.setButton1Text(R.string.uninstall_text).setButton1Positive(false);
return enabled;
}
@VisibleForTesting
boolean handleDisableable(AppEntry appEntry, PackageInfo packageInfo) {
boolean disableable = false;
// Try to prevent the user from bricking their phone
// by not allowing disabling of apps signed with the
// system cert and any launcher app in the system.
if (mHomePackages.contains(appEntry.info.packageName)
|| Utils.isSystemPackage(mContext.getResources(), mPm, packageInfo)) {
// Disable button for core system applications.
mActionButtons
.setButton1Text(R.string.disable_text)
.setButton1Positive(false);
} else if (appEntry.info.enabled && appEntry.info.enabledSetting
!= PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
mActionButtons
.setButton1Text(R.string.disable_text)
.setButton1Positive(false);
disableable = !mApplicationFeatureProvider.getKeepEnabledPackages()
.contains(appEntry.info.packageName);
} else {
mActionButtons
.setButton1Text(R.string.enable_text)
.setButton1Positive(true);
disableable = true;
}
return disableable;
}
private void updateForceStopButton(boolean enabled) {
final boolean disallowedBySystem = RestrictedLockUtils.hasBaseUserRestriction(
mContext, UserManager.DISALLOW_APPS_CONTROL, mUserId);
mActionButtons
.setButton2Enabled(disallowedBySystem ? false : enabled)
.setButton2OnClickListener(
disallowedBySystem ? null : v -> mParent.handleForceStopButtonClick());
}
void checkForceStop(AppEntry appEntry, PackageInfo packageInfo) {
if (mDpm.packageHasActiveAdmins(packageInfo.packageName)) {
// User can't force stop device admin.
Log.w(TAG, "User can't force stop device admin");
updateForceStopButton(false);
} else if (mPm.isPackageStateProtected(packageInfo.packageName,
UserHandle.getUserId(appEntry.info.uid))) {
Log.w(TAG, "User can't force stop protected packages");
updateForceStopButton(false);
} else if (AppUtils.isInstant(packageInfo.applicationInfo)) {
updateForceStopButton(false);
mActionButtons.setButton2Visible(false);
} else if ((appEntry.info.flags & ApplicationInfo.FLAG_STOPPED) == 0) {
// If the app isn't explicitly stopped, then always show the
// force stop button.
Log.w(TAG, "App is not explicitly stopped");
updateForceStopButton(true);
} else {
final Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,
Uri.fromParts("package", appEntry.info.packageName, null));
intent.putExtra(Intent.EXTRA_PACKAGES, new String[] {appEntry.info.packageName});
intent.putExtra(Intent.EXTRA_UID, appEntry.info.uid);
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(appEntry.info.uid));
Log.d(TAG, "Sending broadcast to query restart status for "
+ appEntry.info.packageName);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null);
}
}
private boolean signaturesMatch(String pkg1, String pkg2) {
if (pkg1 != null && pkg2 != null) {
try {
return mPm.checkSignatures(pkg1, pkg2) >= PackageManager.SIGNATURE_MATCH;
} catch (Exception e) {
// e.g. named alternate package not found during lookup;
// this is an expected case sometimes
}
}
return false;
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.fuelgauge;
package com.android.settings.applications.appinfo;
import android.app.Activity;
import android.app.ActivityManager;
@@ -49,13 +49,13 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -74,8 +74,7 @@ import java.util.List;
* An easy way to handle them is to delegate them to {@link #handleDialogClick(int)} and
* {@link #handleActivityResult(int, int, Intent)} in this controller.
*/
//TODO(80312809): Merge this class into {@link AppActionButtonPreferenceController}
public class AppButtonsPreferenceController extends AbstractPreferenceController implements
public class AppButtonsPreferenceController extends BasePreferenceController implements
PreferenceControllerMixin, LifecycleObserver, OnResume, OnDestroy,
ApplicationsState.Callbacks {
public static final String APP_CHG = "chg";
@@ -120,9 +119,8 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
public AppButtonsPreferenceController(SettingsActivity activity, Fragment fragment,
Lifecycle lifecycle, String packageName, ApplicationsState state,
DevicePolicyManager dpm, UserManager userManager,
PackageManager packageManager, int requestUninstall, int requestRemoveDeviceAdmin) {
super(activity);
int requestUninstall, int requestRemoveDeviceAdmin) {
super(activity, KEY_ACTION_BUTTONS);
if (!(fragment instanceof ButtonActionDialogFragment.AppButtonsDialogListener)) {
throw new IllegalArgumentException(
@@ -133,9 +131,9 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
mMetricsFeatureProvider = factory.getMetricsFeatureProvider();
mApplicationFeatureProvider = factory.getApplicationFeatureProvider(activity);
mState = state;
mDpm = dpm;
mUserManager = userManager;
mPm = packageManager;
mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPm = activity.getPackageManager();
mPackageName = packageName;
mActivity = activity;
mFragment = fragment;
@@ -153,9 +151,10 @@ public class AppButtonsPreferenceController extends AbstractPreferenceController
}
@Override
public boolean isAvailable() {
public int getAvailabilityStatus() {
// TODO(b/37313605): Re-enable once this controller supports instant apps
return mAppEntry != null && !AppUtils.isInstant(mAppEntry.info);
return mAppEntry != null && !AppUtils.isInstant(mAppEntry.info)
? AVAILABLE : DISABLED_FOR_USER ;
}
@Override

View File

@@ -19,14 +19,12 @@ package com.android.settings.applications.appinfo;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
@@ -35,7 +33,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -47,7 +44,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.DeviceAdminAdd;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
@@ -62,7 +58,6 @@ import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -77,7 +72,8 @@ import java.util.List;
* uninstall the application.
*/
public class AppInfoDashboardFragment extends DashboardFragment
implements ApplicationsState.Callbacks {
implements ApplicationsState.Callbacks,
ButtonActionDialogFragment.AppButtonsDialogListener {
private static final String TAG = "AppInfoDashboard";
@@ -101,10 +97,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
// Dialog identifiers used in showDialog
private static final int DLG_BASE = 0;
private static final int DLG_FORCE_STOP = DLG_BASE + 1;
private static final int DLG_DISABLE = DLG_BASE + 2;
private static final int DLG_SPECIAL_DISABLE = DLG_BASE + 3;
static final int DLG_CLEAR_INSTANT_APP = DLG_BASE + 4;
static final int DLG_CLEAR_INSTANT_APP = DLG_BASE + 1;
public static final String ARG_PACKAGE_NAME = "package";
public static final String ARG_PACKAGE_UID = "uid";
@@ -132,12 +125,11 @@ public class AppInfoDashboardFragment extends DashboardFragment
private boolean mInitialized;
private boolean mShowUninstalled;
private boolean mUpdatedSysApp = false;
private boolean mDisableAfterUninstall;
private List<Callback> mCallbacks = new ArrayList<>();
private InstantAppButtonsPreferenceController mInstantAppButtonPreferenceController;
private AppActionButtonPreferenceController mAppActionButtonPreferenceController;
private AppButtonsPreferenceController mAppButtonsPreferenceController;
/**
* Callback to invoke when app info has been changed.
@@ -146,11 +138,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
void refreshUi();
}
private boolean isDisabledUntilUsed() {
return mAppEntry.info.enabledSetting
== PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
@@ -262,9 +249,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
// when app state changes.
controllers.add(
new AppHeaderViewPreferenceController(context, this, packageName, lifecycle));
mAppActionButtonPreferenceController =
new AppActionButtonPreferenceController(context, this, packageName);
controllers.add(mAppActionButtonPreferenceController);
for (AbstractPreferenceController controller : controllers) {
mCallbacks.add((Callback) controller);
@@ -275,6 +259,10 @@ public class AppInfoDashboardFragment extends DashboardFragment
mInstantAppButtonPreferenceController =
new InstantAppButtonsPreferenceController(context, this, packageName, lifecycle);
controllers.add(mInstantAppButtonPreferenceController);
mAppButtonsPreferenceController = new AppButtonsPreferenceController(
(SettingsActivity) getActivity(), this, lifecycle, packageName, mState,
REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
controllers.add(mAppButtonsPreferenceController);
controllers.add(new AppBatteryPreferenceController(context, this, packageName, lifecycle));
controllers.add(new AppMemoryPreferenceController(context, this, lifecycle));
controllers.add(new DefaultHomeShortcutPreferenceController(context, packageName));
@@ -374,30 +362,19 @@ public class AppInfoDashboardFragment extends DashboardFragment
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_UNINSTALL:
// Refresh option menu
getActivity().invalidateOptionsMenu();
if (requestCode == REQUEST_UNINSTALL) {
// Refresh option menu
getActivity().invalidateOptionsMenu();
}
if (mAppButtonsPreferenceController != null) {
mAppButtonsPreferenceController.handleActivityResult(requestCode, resultCode, data);
}
}
if (mDisableAfterUninstall) {
mDisableAfterUninstall = false;
new DisableChanger(this, mAppEntry.info,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
.execute((Object) null);
}
if (!refreshUi()) {
onPackageRemoved();
} else {
startListeningToPackageRemove();
}
break;
case REQUEST_REMOVE_DEVICE_ADMIN:
if (!refreshUi()) {
setIntentAndFinish(true, true);
} else {
startListeningToPackageRemove();
}
break;
@Override
public void handleDialogClick(int id) {
if (mAppButtonsPreferenceController != null) {
mAppButtonsPreferenceController.handleDialogClick(id);
}
}
@@ -442,6 +419,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
for (Callback callback : mCallbacks) {
callback.refreshUi();
}
mAppButtonsPreferenceController.refreshUi();
if (!mInitialized) {
// First time init: are we displaying an uninstalled app?
@@ -471,53 +449,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
@VisibleForTesting
AlertDialog createDialog(int id, int errorCode) {
switch (id) {
case DLG_DISABLE:
return new AlertDialog.Builder(getActivity())
.setMessage(getActivity().getText(R.string.app_disable_dlg_text))
.setPositiveButton(R.string.app_disable_dlg_positive,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Disable the app
mMetricsFeatureProvider.action(getContext(),
MetricsEvent.ACTION_SETTINGS_DISABLE_APP);
new DisableChanger(AppInfoDashboardFragment.this,
mAppEntry.info,
PackageManager
.COMPONENT_ENABLED_STATE_DISABLED_USER)
.execute((Object) null);
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
case DLG_SPECIAL_DISABLE:
return new AlertDialog.Builder(getActivity())
.setMessage(getActivity().getText(R.string.app_disable_dlg_text))
.setPositiveButton(R.string.app_disable_dlg_positive,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Disable the app and ask for uninstall
mMetricsFeatureProvider.action(getContext(),
MetricsEvent.ACTION_SETTINGS_DISABLE_APP);
uninstallPkg(mAppEntry.info.packageName,
false, true);
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
case DLG_FORCE_STOP:
return new AlertDialog.Builder(getActivity())
.setTitle(getActivity().getText(R.string.force_stop_dlg_title))
.setMessage(getActivity().getText(R.string.force_stop_dlg_text))
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Force stop
forceStopPackage(mAppEntry.info.packageName);
}
})
.setNegativeButton(R.string.dlg_cancel, null)
.create();
}
return mInstantAppButtonPreferenceController.createDialog(id);
}
@@ -530,22 +461,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
mMetricsFeatureProvider.action(
getContext(), MetricsEvent.ACTION_SETTINGS_UNINSTALL_APP);
startActivityForResult(uninstallIntent, REQUEST_UNINSTALL);
mDisableAfterUninstall = andDisable;
}
private void forceStopPackage(String pkgName) {
mMetricsFeatureProvider.action(getContext(), MetricsEvent.ACTION_APP_FORCE_STOP, pkgName);
final ActivityManager am = (ActivityManager) getActivity().getSystemService(
Context.ACTIVITY_SERVICE);
Log.d(TAG, "Stopping package " + pkgName);
am.forceStopPackage(pkgName);
final int userId = UserHandle.getUserId(mAppEntry.info.uid);
mState.invalidatePackage(pkgName, userId);
final AppEntry newEnt = mState.getEntry(pkgName, userId);
if (newEnt != null) {
mAppEntry = newEnt;
}
mAppActionButtonPreferenceController.checkForceStop(mAppEntry, mPackageInfo);
}
public static void startAppInfoFragment(Class<?> fragment, int title, Bundle args,
@@ -565,74 +480,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
.launch();
}
void handleUninstallButtonClick() {
if (mAppEntry == null) {
setIntentAndFinish(true, true);
return;
}
final String packageName = mAppEntry.info.packageName;
if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
stopListeningToPackageRemove();
final Activity activity = getActivity();
final Intent uninstallDAIntent = new Intent(activity, DeviceAdminAdd.class);
uninstallDAIntent.putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME,
mPackageName);
mMetricsFeatureProvider.action(
activity, MetricsEvent.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN);
activity.startActivityForResult(uninstallDAIntent, REQUEST_REMOVE_DEVICE_ADMIN);
return;
}
final EnforcedAdmin admin = RestrictedLockUtils.checkIfUninstallBlocked(getActivity(),
packageName, mUserId);
final boolean uninstallBlockedBySystem = mAppsControlDisallowedBySystem ||
RestrictedLockUtils.hasBaseUserRestriction(getActivity(), packageName, mUserId);
if (admin != null && !uninstallBlockedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(getActivity(), admin);
} else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
if (mAppEntry.info.enabled && !isDisabledUntilUsed()) {
// If the system app has an update and this is the only user on the device,
// then offer to downgrade the app, otherwise only offer to disable the
// app for this user.
if (mUpdatedSysApp && isSingleUser()) {
showDialogInner(DLG_SPECIAL_DISABLE, 0);
} else {
showDialogInner(DLG_DISABLE, 0);
}
} else {
mMetricsFeatureProvider.action(
getActivity(),
MetricsEvent.ACTION_SETTINGS_ENABLE_APP);
new DisableChanger(this, mAppEntry.info,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED)
.execute((Object) null);
}
} else if ((mAppEntry.info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
uninstallPkg(packageName, true, false);
} else {
uninstallPkg(packageName, false, false);
}
}
void handleForceStopButtonClick() {
if (mAppEntry == null) {
setIntentAndFinish(true, true);
return;
}
if (mAppsControlDisallowedAdmin != null && !mAppsControlDisallowedBySystem) {
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
getActivity(), mAppsControlDisallowedAdmin);
} else {
showDialogInner(DLG_FORCE_STOP, 0);
//forceStopPackage(mAppInfo.packageName);
}
}
/** Returns whether there is only one user on this device, not including the system-only user */
private boolean isSingleUser() {
final int userCount = mUserManager.getUserCount();
return userCount == 1 || (mUserManager.isSplitSystemUser() && userCount == 2);
}
private void onPackageRemoved() {
getActivity().finishActivity(SUB_INFO_FRAGMENT);
getActivity().finishAndRemoveTask();
@@ -659,26 +506,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
return count;
}
private static class DisableChanger extends AsyncTask<Object, Object, Object> {
final PackageManager mPm;
final WeakReference<AppInfoDashboardFragment> mActivity;
final ApplicationInfo mInfo;
final int mState;
DisableChanger(AppInfoDashboardFragment activity, ApplicationInfo info, int state) {
mPm = activity.mPm;
mActivity = new WeakReference<AppInfoDashboardFragment>(activity);
mInfo = info;
mState = state;
}
@Override
protected Object doInBackground(Object... params) {
mPm.setApplicationEnabledSetting(mInfo.packageName, mState, 0);
return null;
}
}
private String getPackageName() {
if (mPackageName != null) {
return mPackageName;

View File

@@ -1,6 +1,5 @@
package com.android.settings.fuelgauge;
package com.android.settings.applications.appinfo;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
@@ -26,7 +25,7 @@ public class ButtonActionDialogFragment extends InstrumentedDialogFragment imple
/**
* Interface to handle the dialog click
*/
interface AppButtonsDialogListener {
public interface AppButtonsDialogListener {
void handleDialogClick(int type);
}

View File

@@ -17,11 +17,9 @@
package com.android.settings.applications.defaultapps;
import android.content.Context;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.ArraySet;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -29,7 +27,6 @@ import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Fragment for choosing default browser.
@@ -61,24 +58,13 @@ public class DefaultBrowserPicker extends DefaultAppPickerFragment {
final List<DefaultAppInfo> candidates = new ArrayList<>();
final Context context = getContext();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = mPm.queryIntentActivitiesAsUser(
DefaultBrowserPreferenceController.BROWSE_PROBE, PackageManager.MATCH_ALL, mUserId);
final List<ResolveInfo> list =
DefaultBrowserPreferenceController.getCandidates(mPm, mUserId);
final int count = list.size();
final Set<String> addedPackages = new ArraySet<>();
for (int i = 0; i < count; i++) {
ResolveInfo info = list.get(i);
if (info.activityInfo == null || !info.handleAllWebDataURI) {
continue;
}
final String packageName = info.activityInfo.packageName;
if (addedPackages.contains(packageName)) {
continue;
}
for (ResolveInfo info : list) {
try {
candidates.add(new DefaultAppInfo(context, mPm,
mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
addedPackages.add(packageName);
mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
} catch (PackageManager.NameNotFoundException e) {
// Skip unknown packages.
}

View File

@@ -26,12 +26,15 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import androidx.preference.Preference;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class DefaultBrowserPreferenceController extends DefaultAppPreferenceController {
@@ -48,7 +51,7 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
@Override
public boolean isAvailable() {
final List<ResolveInfo> candidates = getCandidates();
final List<ResolveInfo> candidates = getCandidates(mPackageManager, mUserId);
return candidates != null && !candidates.isEmpty();
}
@@ -103,14 +106,31 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
return getOnlyAppIcon();
}
private List<ResolveInfo> getCandidates() {
return mPackageManager.queryIntentActivitiesAsUser(BROWSE_PROBE, PackageManager.MATCH_ALL,
mUserId);
static List<ResolveInfo> getCandidates(PackageManager packageManager, int userId) {
final List<ResolveInfo> candidates = new ArrayList<>();
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = packageManager.queryIntentActivitiesAsUser(
BROWSE_PROBE, PackageManager.MATCH_ALL, userId);
if (list != null) {
final Set<String> addedPackages = new ArraySet<>();
for (ResolveInfo info : list) {
if (info.activityInfo == null || !info.handleAllWebDataURI) {
continue;
}
final String packageName = info.activityInfo.packageName;
if (addedPackages.contains(packageName)) {
continue;
}
candidates.add(info);
addedPackages.add(packageName);
}
}
return candidates;
}
private String getOnlyAppLabel() {
// Resolve that intent and check that the handleAllWebDataURI boolean is set
final List<ResolveInfo> list = getCandidates();
final List<ResolveInfo> list = getCandidates(mPackageManager, mUserId);
if (list != null && list.size() == 1) {
final ResolveInfo info = list.get(0);
final String label = info.loadLabel(mPackageManager).toString();
@@ -123,7 +143,7 @@ public class DefaultBrowserPreferenceController extends DefaultAppPreferenceCont
}
private Drawable getOnlyAppIcon() {
final List<ResolveInfo> list = getCandidates();
final List<ResolveInfo> list = getCandidates(mPackageManager, mUserId);
if (list != null && list.size() == 1) {
final ResolveInfo info = list.get(0);
final ComponentInfo cn = info.getComponentInfo();

View File

@@ -15,20 +15,17 @@
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class DataSaverController extends BasePreferenceController {
@VisibleForTesting static final String KEY_DATA_SAVER = "data_saver";
public DataSaverController(Context context) {
super(context, KEY_DATA_SAVER);
public DataSaverController(Context context, String key) {
super(context, key);
}
@AvailabilityStatus

View File

@@ -14,20 +14,17 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class DeviceAdministratorsController extends BasePreferenceController {
@VisibleForTesting static final String KEY_DEVICE_ADMIN = "device_administrators";
public DeviceAdministratorsController(Context context) {
super(context, KEY_DEVICE_ADMIN);
public DeviceAdministratorsController(Context context, String key) {
super(context, key);
}
@AvailabilityStatus

View File

@@ -14,25 +14,24 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import android.app.ActivityManager;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class EnabledVrListenersController extends BasePreferenceController {
@VisibleForTesting static final String KEY_ENABLED_VR_LISTENERS = "enabled_vr_listeners";
public EnabledVrListenersController(Context context) {
super(context, KEY_ENABLED_VR_LISTENERS);
public EnabledVrListenersController(Context context, String key) {
super(context, key);
}
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(R.bool.config_show_enabled_vr_listeners)
&& !ActivityManager.isLowRamDeviceStatic()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}

View File

@@ -14,20 +14,17 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class HighPowerAppsController extends BasePreferenceController {
@VisibleForTesting static final String KEY_HIGH_POWER_APPS = "high_power_apps";
public HighPowerAppsController(Context context) {
super(context, KEY_HIGH_POWER_APPS);
public HighPowerAppsController(Context context, String key) {
super(context, key);
}
@AvailabilityStatus

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess;
import android.app.ActivityManager;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
public class NotificationAccessController extends BasePreferenceController {
public NotificationAccessController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return !ActivityManager.isLowRamDeviceStatic()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess;
import android.app.ActivityManager;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
public class PictureInPictureController extends BasePreferenceController {
public PictureInPictureController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return !ActivityManager.isLowRamDeviceStatic()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -14,20 +14,17 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import android.content.Context;
import androidx.annotation.VisibleForTesting;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
public class PremiumSmsController extends BasePreferenceController {
@VisibleForTesting static final String KEY_PREMIUM_SMS = "premium_sms";
public PremiumSmsController(Context context) {
super(context, KEY_PREMIUM_SMS);
public PremiumSmsController(Context context, String key) {
super(context, key);
}
@AvailabilityStatus

View File

@@ -0,0 +1,65 @@
/*
* 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.applications.specialaccess;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable
public class SpecialAccessSettings extends DashboardFragment {
private static final String TAG = "SpecialAccessSettings";
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.special_access;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SPECIAL_ACCESS;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.special_access;
result.add(sir);
return result;
}
};
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess;
import android.app.ActivityManager;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
public class ZenAccessController extends BasePreferenceController {
public ZenAccessController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return !ActivityManager.isLowRamDeviceStatic()
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -97,6 +97,11 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
if (DBG) {
Log.d(TAG, "isFilterMatched() current audio profile : " + currentAudioProfile);
}
// If device is Hearing Aid, it is compatible with HFP and A2DP.
// It would show in Available Devices group.
if (cachedDevice.isConnectedHearingAidDevice()) {
return true;
}
// According to the current audio profile type,
// this page will show the bluetooth device that have corresponding profile.
// For example:

View File

@@ -101,6 +101,11 @@ public class ConnectedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
if (DBG) {
Log.d(TAG, "isFilterMatched() current audio profile : " + currentAudioProfile);
}
// If device is Hearing Aid, it is compatible with HFP and A2DP.
// It would not show in Connected Devices group.
if (cachedDevice.isConnectedHearingAidDevice()) {
return false;
}
// According to the current audio profile type,
// this page will show the bluetooth device that doesn't have corresponding profile.
// For example:

View File

@@ -76,9 +76,11 @@ public class ConnectedDeviceGroupController extends BasePreferenceController
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
final Context context = screen.getContext();
mBluetoothDeviceUpdater.setPrefContext(context);
mBluetoothDeviceUpdater.forceUpdate();
mConnectedUsbDeviceUpdater.initUsbPreference(screen.getContext());
mConnectedUsbDeviceUpdater.initUsbPreference(context);
mConnectedDockUpdater.setPreferenceContext(context);
mConnectedDockUpdater.forceUpdate();
}
}

View File

@@ -75,8 +75,11 @@ public class SavedDeviceGroupController extends BasePreferenceController
if (isAvailable()) {
mPreferenceGroup = (PreferenceGroup) screen.findPreference(KEY);
mPreferenceGroup.setVisible(false);
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
final Context context = screen.getContext();
mBluetoothDeviceUpdater.setPrefContext(context);
mBluetoothDeviceUpdater.forceUpdate();
mSavedDockUpdater.setPreferenceContext(context);
mSavedDockUpdater.forceUpdate();
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.connecteddevice.dock;
import android.annotation.NonNull;
import android.content.Context;
/**
@@ -40,4 +41,10 @@ public interface DockUpdater {
*/
default void forceUpdate() {
}
/**
* Set the context to generate the {@link Preference}, so it could get the correct theme.
*/
default void setPreferenceContext(@NonNull Context preferenceContext) {
}
}

View File

@@ -78,7 +78,7 @@ public class BaseTimeZoneAdapter<T extends BaseTimeZoneAdapter.AdapterItem>
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch(viewType) {
case TYPE_HEADER: {
final View view = inflater.inflate(R.layout.preference_category_material_settings,
final View view = inflater.inflate(R.layout.preference_category_material,
parent, false);
return new HeaderViewHolder(view);
}

View File

@@ -16,7 +16,9 @@
package com.android.settings.development.qstile;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
@@ -25,7 +27,6 @@ import android.os.SystemProperties;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import androidx.annotation.VisibleForTesting;
import android.util.Log;
import android.view.IWindowManager;
import android.view.ThreadedRenderer;
@@ -34,9 +35,12 @@ import android.view.WindowManagerGlobal;
import android.widget.Toast;
import com.android.internal.app.LocalePicker;
import com.android.internal.statusbar.IStatusBarService;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
import com.android.settingslib.development.SystemPropPoker;
import androidx.annotation.VisibleForTesting;
public abstract class DevelopmentTiles extends TileService {
private static final String TAG = "DevelopmentTiles";
@@ -58,6 +62,20 @@ public abstract class DevelopmentTiles extends TileService {
setIsEnabled(false);
SystemPropPoker.getInstance().poke();
}
final ComponentName cn = new ComponentName(getPackageName(), getClass().getName());
try {
getPackageManager().setComponentEnabledSetting(
cn, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
final IStatusBarService statusBarService = IStatusBarService.Stub.asInterface(
ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
if (statusBarService != null) {
statusBarService.remTile(cn);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to modify QS tile for component " +
cn.toString(), e);
}
state = Tile.STATE_UNAVAILABLE;
} else {
state = isEnabled() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;

View File

@@ -402,10 +402,14 @@ public class StorageItemPreferenceController extends AbstractPreferenceControlle
try {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
// b/33117269: Note that launchIntent may launch activity in different task which set
// different launchMode (e.g. Files), using startActivityForesult to set task as
// source task, and set requestCode as 0 means don't care about returnCode currently.
if (userId == -1) {
mFragment.startActivity(intent);
mFragment.startActivityForResult(intent, 0 /* requestCode not used */);
} else {
mFragment.getActivity().startActivityAsUser(intent, new UserHandle(userId));
mFragment.getActivity().startActivityForResultAsUser(intent,
0 /* requestCode not used */, new UserHandle(userId));
}
} catch (ActivityNotFoundException e) {
Log.w(TAG, "No activity found for " + intent);

View File

@@ -22,7 +22,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import androidx.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.util.IconDrawableFactory;
import android.view.View;
@@ -37,28 +36,32 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import androidx.annotation.VisibleForTesting;
public class AppGridView extends GridView {
public AppGridView(Context context) {
this(context, null);
super(context);
init(context);
}
public AppGridView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
super(context, attrs);
init(context);
}
public AppGridView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
super(context, attrs, defStyleAttr);
init(context);
}
public AppGridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleResId) {
super(context, attrs, defStyleAttr, defStyleResId);
setNumColumns(AUTO_FIT);
init(context);
final int columnWidth = getResources().getDimensionPixelSize(
R.dimen.screen_zoom_preview_app_icon_width);
setColumnWidth(columnWidth);
}
private void init(Context context) {
setAdapter(new AppsAdapter(context, R.layout.screen_zoom_preview_app_icon,
android.R.id.text1, android.R.id.icon1));
}
@@ -105,6 +108,7 @@ public class AppGridView extends GridView {
}
private void loadAllApps() {
final int needAppCount = 6;
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
@@ -117,6 +121,9 @@ public class AppGridView extends GridView {
if (label != null) {
results.add(new ActivityEntry(info, label.toString(), iconFactory));
}
if (results.size() >= needAppCount) {
break;
}
}
Collections.sort(results);

View File

@@ -20,7 +20,6 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.LoaderManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
@@ -28,7 +27,6 @@ import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import android.text.TextUtils;
@@ -43,6 +41,8 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.applications.appinfo.AppButtonsPreferenceController;
import com.android.settings.applications.appinfo.ButtonActionDialogFragment;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
@@ -112,9 +112,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
private AppButtonsPreferenceController mAppButtonsPreferenceController;
private BackgroundActivityPreferenceController mBackgroundActivityPreferenceController;
private DevicePolicyManager mDpm;
private UserManager mUserManager;
private PackageManager mPackageManager;
private List<Anomaly> mAnomalies;
private String mPackageName;
@@ -203,9 +200,6 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
super.onAttach(activity);
mState = ApplicationsState.getInstance(getActivity().getApplication());
mDpm = (DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE);
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPackageManager = activity.getPackageManager();
mBatteryUtils = BatteryUtils.getInstance(getContext());
}
@@ -332,8 +326,8 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
controllers.add(new BatteryOptimizationPreferenceController(
(SettingsActivity) getActivity(), this, packageName));
mAppButtonsPreferenceController = new AppButtonsPreferenceController(
(SettingsActivity) getActivity(), this, getLifecycle(), packageName, mState, mDpm,
mUserManager, mPackageManager, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
(SettingsActivity) getActivity(), this, getLifecycle(), packageName, mState,
REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN);
controllers.add(mAppButtonsPreferenceController);
return controllers;

View File

@@ -43,6 +43,7 @@ import com.android.settingslib.core.lifecycle.events.OnStop;
public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
private static final String TAG = "AutoBatterySeekBarPreferenceController";
private static final int INTERVAL = 5;
@VisibleForTesting
static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
private SeekBarPreference mPreference;
@@ -92,7 +93,7 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
public boolean onPreferenceChange(Preference preference, Object newValue) {
final int progress = (int) newValue;
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, progress);
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, progress * INTERVAL);
return true;
}
@@ -102,7 +103,7 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
// Override the max value with LOW_POWER_MODE_TRIGGER_LEVEL_MAX, if set.
final int maxLevel = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0) / INTERVAL;
if (maxLevel > 0) {
if (!(preference instanceof SeekBarPreference)) {
Log.e(TAG, "Unexpected preference class: " + preference.getClass());
@@ -127,7 +128,7 @@ public class AutoBatterySeekBarPreferenceController extends BasePreferenceContro
preference.setTitle(mContext.getString(R.string.battery_saver_seekbar_title,
Utils.formatPercentage(level)));
SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
seekBarPreference.setProgress(level);
seekBarPreference.setProgress(level / INTERVAL);
seekBarPreference.setSeekBarContentDescription(
mContext.getString(R.string.battery_saver_turn_on_automatically_title));
}

View File

@@ -157,7 +157,7 @@ public class AnomalyDetectionJobService extends JobService {
metricsFeatureProvider.action(context,
MetricsProto.MetricsEvent.ACTION_ANOMALY_IGNORED,
packageName,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,
Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE,
anomalyInfo.anomalyType),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE,
versionCode));

View File

@@ -43,6 +43,7 @@ import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
@@ -54,7 +55,7 @@ import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.dataconnection.ApnSetting;
import com.android.internal.telephony.dataconnection.ApnSettingUtils;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.settings.R;
@@ -336,7 +337,8 @@ public class ApnSettings extends RestrictedSettingsFragment implements
ArrayList<ApnPreference> mvnoList, IccRecords r, String mvnoType,
String mvnoMatchData) {
if (r != null && !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)) {
if (ApnSetting.mvnoMatches(r, mvnoType, mvnoMatchData)) {
if (ApnSettingUtils.mvnoMatches(r, ApnSetting.getMvnoTypeIntFromString(mvnoType),
mvnoMatchData)) {
mvnoList.add(pref);
// Since adding to mvno list, save mvno info
mMvnoType = mvnoType;

View File

@@ -17,7 +17,6 @@ package com.android.settings.nfc;
import android.content.Context;
import android.nfc.NfcAdapter;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
@@ -26,15 +25,12 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import java.util.List;
public class AndroidBeamPreferenceController extends BasePreferenceController
implements LifecycleObserver, OnResume, OnPause {
public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
private final NfcAdapter mNfcAdapter;
private AndroidBeamEnabler mAndroidBeamEnabler;
private NfcAirplaneModeObserver mAirplaneModeObserver;
public AndroidBeamPreferenceController(Context context, String key) {
super(context, key);
@@ -52,12 +48,6 @@ public class AndroidBeamPreferenceController extends BasePreferenceController
final RestrictedPreference restrictedPreference =
(RestrictedPreference) screen.findPreference(getPreferenceKey());
mAndroidBeamEnabler = new AndroidBeamEnabler(mContext, restrictedPreference);
// Manually set dependencies for NFC when not toggleable.
if (!NfcPreferenceController.isToggleableInAirplaneMode(mContext)) {
mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
(Preference) restrictedPreference);
}
}
@Override
@@ -70,9 +60,6 @@ public class AndroidBeamPreferenceController extends BasePreferenceController
@Override
public void onResume() {
if (mAirplaneModeObserver != null) {
mAirplaneModeObserver.register();
}
if (mAndroidBeamEnabler != null) {
mAndroidBeamEnabler.resume();
}
@@ -80,9 +67,6 @@ public class AndroidBeamPreferenceController extends BasePreferenceController
@Override
public void onPause() {
if (mAirplaneModeObserver != null) {
mAirplaneModeObserver.unregister();
}
if (mAndroidBeamEnabler != null) {
mAndroidBeamEnabler.pause();
}

View File

@@ -28,7 +28,7 @@ import androidx.preference.Preference;
* preference. It will receive intent and update state to ensure preference show correct state.
*/
public abstract class BaseNfcEnabler {
private final Context mContext;
protected final Context mContext;
protected final NfcAdapter mNfcAdapter;
private final IntentFilter mIntentFilter;

View File

@@ -70,12 +70,13 @@ public class NfcAirplaneModeObserver extends ContentObserver {
}
mAirplaneMode = airplaneMode;
boolean toggleable = mAirplaneMode != 1;
if (toggleable) {
mNfcAdapter.enable();
} else {
if (mAirplaneMode == 1) {
// airplane mode is on, need to turn off NFC, and check if user can toggle it
mNfcAdapter.disable();
mPreference.setEnabled(NfcPreferenceController.isToggleableInAirplaneMode(mContext));
} else {
// airplane mode is off, no restriction
mPreference.setEnabled(true);
}
mPreference.setEnabled(toggleable);
}
}

View File

@@ -18,8 +18,10 @@ package com.android.settings.nfc;
import android.content.Context;
import android.nfc.NfcAdapter;
import androidx.preference.SwitchPreference;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
import androidx.preference.SwitchPreference;
/**
* NfcEnabler is a helper to manage the Nfc on/off checkbox preference. It turns on/off Nfc
@@ -38,7 +40,7 @@ public class NfcEnabler extends BaseNfcEnabler {
switch (newState) {
case NfcAdapter.STATE_OFF:
mPreference.setChecked(false);
mPreference.setEnabled(true);
mPreference.setEnabled(isToggleable());
break;
case NfcAdapter.STATE_ON:
mPreference.setChecked(true);
@@ -54,4 +56,15 @@ public class NfcEnabler extends BaseNfcEnabler {
break;
}
}
@VisibleForTesting
boolean isToggleable() {
if (NfcPreferenceController.isToggleableInAirplaneMode(mContext)
|| !NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)) {
return true;
}
final int airplaneMode = Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
return airplaneMode != 1;
}
}

View File

@@ -20,7 +20,7 @@ import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
@@ -37,7 +37,8 @@ public class NfcPreferenceController extends TogglePreferenceController
public static final String KEY_TOGGLE_NFC = "toggle_nfc";
private final NfcAdapter mNfcAdapter;
private NfcEnabler mNfcEnabler;
private NfcAirplaneModeObserver mAirplaneModeObserver;
@VisibleForTesting
NfcAirplaneModeObserver mAirplaneModeObserver;
public NfcPreferenceController(Context context, String key) {
super(context, key);
@@ -57,10 +58,10 @@ public class NfcPreferenceController extends TogglePreferenceController
mNfcEnabler = new NfcEnabler(mContext, switchPreference);
// Manually set dependencies for NFC when not toggleable.
if (!isToggleableInAirplaneMode(mContext)) {
mAirplaneModeObserver = new NfcAirplaneModeObserver(mContext,
mNfcAdapter, (Preference) switchPreference);
// Listen to airplane mode updates if NFC should be turned off when airplane mode is on
if (shouldTurnOffNFCInAirplaneMode(mContext) || isToggleableInAirplaneMode(mContext)) {
mAirplaneModeObserver =
new NfcAirplaneModeObserver(mContext, mNfcAdapter, switchPreference);
}
}
@@ -125,6 +126,12 @@ public class NfcPreferenceController extends TogglePreferenceController
}
}
public static boolean shouldTurnOffNFCInAirplaneMode(Context context) {
final String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS);
return airplaneModeRadios != null && airplaneModeRadios.contains(Settings.Global.RADIO_NFC);
}
public static boolean isToggleableInAirplaneMode(Context context) {
final String toggleable = Settings.Global.getString(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);

View File

@@ -39,6 +39,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import androidx.annotation.StringRes;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import android.text.TextUtils;
@@ -124,7 +125,8 @@ public class ChooseLockGeneric extends SettingsActivity {
*/
public static final String EXTRA_CHOOSE_LOCK_GENERIC_EXTRAS = "choose_lock_generic_extras";
private static final int CONFIRM_EXISTING_REQUEST = 100;
@VisibleForTesting
static final int CONFIRM_EXISTING_REQUEST = 100;
private static final int ENABLE_ENCRYPTION_REQUEST = 101;
private static final int CHOOSE_LOCK_REQUEST = 102;
private static final int CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST = 103;
@@ -329,7 +331,9 @@ public class ChooseLockGeneric extends SettingsActivity {
mWaitingForConfirmation = false;
if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == Activity.RESULT_OK) {
mPasswordConfirmed = true;
mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
mUserPassword = data != null
? data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
: null;
updatePreferencesOrFinish(false /* isRecreatingActivity */);
if (mForChangeCredRequiredForBoot) {
if (!TextUtils.isEmpty(mUserPassword)) {
@@ -394,7 +398,8 @@ public class ChooseLockGeneric extends SettingsActivity {
}
}
private void updatePreferencesOrFinish(boolean isRecreatingActivity) {
@VisibleForTesting
void updatePreferencesOrFinish(boolean isRecreatingActivity) {
Intent intent = getActivity().getIntent();
int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
if (quality == -1) {

View File

@@ -38,7 +38,8 @@ public class VpnUtils {
private static final String TAG = "VpnUtils";
public static String getLockdownVpn() {
final byte[] value = KeyStore.getInstance().get(Credentials.LOCKDOWN_VPN);
final byte[] value = KeyStore.getInstance().get(
Credentials.LOCKDOWN_VPN, true /* suppressKeyNotFoundWarning */);
return value == null ? null : new String(value);
}

View File

@@ -255,9 +255,15 @@ public class UsageGraph extends View {
return;
}
canvas.save();
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
// Flip the canvas along the y-axis of the center of itself before drawing paths.
canvas.scale(-1, 1, canvas.getWidth() * 0.5f, 0);
}
drawLinePath(canvas, mLocalProjectedPaths, mDottedPaint);
drawFilledPath(canvas, mLocalPaths, mFillPaint);
drawLinePath(canvas, mLocalPaths, mLinePaint);
canvas.restore();
BatteryUtils.logRuntime(LOG_TAG, "onDraw", startTime);
}

View File

@@ -1,4 +1,4 @@
com.android.settings.applications.appinfo.AppActionButtonPreferenceController
com.android.settings.applications.appinfo.AppButtonsPreferenceController
com.android.settings.applications.appinfo.AppBatteryPreferenceController
com.android.settings.applications.appinfo.AppHeaderViewPreferenceController
com.android.settings.applications.appinfo.AppMemoryPreferenceController

View File

@@ -1,79 +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.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class SpecialAccessSettingsTest {
private Context mContext;
private SpecialAccessSettings mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mFragment = new SpecialAccessSettings() {
@Override
public Context getContext() {
return mContext;
}
};
}
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
SpecialAccessSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext,
true /* enabled */);
final List<String> niks =
SpecialAccessSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(R.xml.special_access);
assertThat(niks).isEmpty();
}
@Test
@Config(qualifiers = "mcc999")
public void testSearchIndexProvider_ifElementsAreNotShown_shouldNotBeIndexed() {
final List<String> niks =
SpecialAccessSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
assertThat(niks).contains(HighPowerAppsController.KEY_HIGH_POWER_APPS);
assertThat(niks).contains(DeviceAdministratorsController.KEY_DEVICE_ADMIN);
assertThat(niks).contains(PremiumSmsController.KEY_PREMIUM_SMS);
assertThat(niks).contains(DataSaverController.KEY_DATA_SAVER);
assertThat(niks).contains(EnabledVrListenersController.KEY_ENABLED_VR_LISTENERS);
}
}

View File

@@ -1,360 +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.applications.appinfo;
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.argThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
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.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest;
import com.android.settingslib.Utils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
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.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class AppActionButtonPreferenceControllerTest {
@Mock
private UserManager mUserManager;
@Mock
private DevicePolicyManager mDevicePolicyManager;
@Mock
private AppInfoDashboardFragment mFragment;
@Mock
private ApplicationInfo mAppInfo;
@Mock
private PackageManager mPackageManager;
private Context mContext;
private AppActionButtonPreferenceController mController;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mContext = spy(RuntimeEnvironment.application);
mController = spy(new AppActionButtonPreferenceController(mContext, mFragment, "Package1"));
mController.mActionButtons = ActionButtonPreferenceTest.createMock();
ReflectionHelpers.setField(mController, "mUserManager", mUserManager);
ReflectionHelpers.setField(mController, "mDpm", mDevicePolicyManager);
ReflectionHelpers.setField(mController, "mApplicationFeatureProvider",
mFeatureFactory.applicationFeatureProvider);
ReflectionHelpers.setField(mController, "mPm", mPackageManager);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
final PackageInfo packageInfo = mock(PackageInfo.class);
packageInfo.applicationInfo = mAppInfo;
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
}
@Test
public void getAvailabilityStatus_notInstantApp_shouldReturnAvailable() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_isInstantApp_shouldReturnDisabled() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true));
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void displayPreference_shouldInitializeForceStopButton() {
final PreferenceScreen screen = mock(PreferenceScreen.class);
final ActionButtonPreference preference = spy(new ActionButtonPreference(mContext));
when(screen.findPreference(mController.getPreferenceKey())).thenReturn(preference);
mController.displayPreference(screen);
verify(preference).setButton2Positive(false);
verify(preference).setButton2Text(R.string.force_stop);
verify(preference).setButton2Enabled(false);
}
@Test
public void refreshUi_shouldRefreshButton() {
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
doNothing().when(mController).checkForceStop(appEntry, packageInfo);
doNothing().when(mController).initUninstallButtons(appEntry, packageInfo);
when(mFragment.getAppEntry()).thenReturn(appEntry);
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
mController.refreshUi();
verify(mController).checkForceStop(appEntry, packageInfo);
verify(mController).initUninstallButtons(appEntry, packageInfo);
}
@Test
public void initUninstallButtonForUserApp_shouldSetNegativeButton() {
final ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_INSTALLED;
info.enabled = true;
final PackageInfo packageInfo = mock(PackageInfo.class);
packageInfo.applicationInfo = info;
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
assertThat(mController.initUninstallButtonForUserApp()).isTrue();
verify(mController.mActionButtons).setButton1Positive(false);
}
// Tests that we don't show the uninstall button for instant apps"
@Test
public void initUninstallButtonForUserApp_instantApps_noUninstallButton() {
// Make this app appear to be instant.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true));
final ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_INSTALLED;
info.enabled = true;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
final PackageInfo packageInfo = mock(PackageInfo.class);
packageInfo.applicationInfo = info;
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
assertThat(mController.initUninstallButtonForUserApp()).isFalse();
verify(mController.mActionButtons).setButton1Visible(false);
}
@Test
public void initUninstallButtonForUserApp_notInstalledForCurrentUser_shouldDisableButton() {
final ApplicationInfo info = new ApplicationInfo();
info.enabled = true;
final PackageInfo packageInfo = mock(PackageInfo.class);
packageInfo.applicationInfo = info;
when(mFragment.getPackageInfo()).thenReturn(packageInfo);
final int userID1 = 1;
final int userID2 = 2;
final List<UserInfo> userInfos = new ArrayList<>();
userInfos.add(new UserInfo(userID1, "User1", UserInfo.FLAG_PRIMARY));
userInfos.add(new UserInfo(userID2, "User2", UserInfo.FLAG_GUEST));
when(mUserManager.getUsers(true)).thenReturn(userInfos);
assertThat(mController.initUninstallButtonForUserApp()).isFalse();
}
// Tests that we don't show the force stop button for instant apps (they aren't allowed to run
// when they aren't in the foreground).
@Test
public void checkForceStop_instantApps_shouldNotShowForceStop() {
// Make this app appear to be instant.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> true));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Visible(false);
}
@Test
public void checkForceStop_isStateProtected_shouldDisableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final String packageName = "Package1";
final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
final ApplicationInfo appInfo = new ApplicationInfo();
appInfo.uid = 42;
appInfo.sourceDir = "source";
final ApplicationsState.AppEntry appEntry = new ApplicationsState.AppEntry(
mContext, appInfo, 0);
when(mPackageManager.isPackageStateProtected(packageName, 0)).thenReturn(true);
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Enabled(false);
}
@Test
public void checkForceStop_hasActiveAdmin_shouldDisableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final String packageName = "Package1";
final PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = packageName;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
when(mDevicePolicyManager.packageHasActiveAdmins(packageName)).thenReturn(true);
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Enabled(false);
}
@Test
public void checkForceStop_appRunning_shouldEnableForceStop() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
mController.checkForceStop(appEntry, packageInfo);
verify(mController.mActionButtons).setButton2Enabled(true);
}
@Test
public void checkForceStop_appStopped_shouldQueryPackageRestart() {
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
(InstantAppDataProvider) (i -> false));
final PackageInfo packageInfo = mock(PackageInfo.class);
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
final ApplicationInfo info = new ApplicationInfo();
appEntry.info = info;
info.flags = ApplicationInfo.FLAG_STOPPED;
info.packageName = "com.android.setting";
mController.checkForceStop(appEntry, packageInfo);
verify(mContext).sendOrderedBroadcastAsUser(argThat(intent -> intent != null
&& intent.getAction().equals(Intent.ACTION_QUERY_PACKAGE_RESTART)),
any(UserHandle.class), nullable(String.class), any(BroadcastReceiver.class),
nullable(Handler.class), anyInt(), nullable(String.class), nullable(Bundle.class));
}
@Test
public void handleDisableable_appIsHomeApp_buttonShouldNotWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
final HashSet<String> homePackages = new HashSet<>();
homePackages.add(info.packageName);
ReflectionHelpers.setField(mController, "mHomePackages", homePackages);
assertThat(mController.handleDisableable(appEntry, mock(PackageInfo.class))).isFalse();
verify(mController.mActionButtons).setButton1Text(R.string.disable_text);
}
@Test
@Config(shadows = ShadowUtils.class)
public void handleDisableable_appIsEnabled_buttonShouldWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
when(mFeatureFactory.applicationFeatureProvider.getKeepEnabledPackages())
.thenReturn(new HashSet<>());
assertThat(mController.handleDisableable(appEntry, mock(PackageInfo.class))).isTrue();
verify(mController.mActionButtons).setButton1Text(R.string.disable_text);
}
@Test
@Config(shadows = ShadowUtils.class)
public void handleDisableable_appIsDisabled_buttonShouldShowEnable() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = false;
info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
when(mFeatureFactory.applicationFeatureProvider.getKeepEnabledPackages())
.thenReturn(new HashSet<>());
assertThat(mController.handleDisableable(appEntry, mock(PackageInfo.class))).isTrue();
verify(mController.mActionButtons).setButton1Text(R.string.enable_text);
verify(mController.mActionButtons).setButton1Positive(true);
}
@Test
@Config(shadows = ShadowUtils.class)
public void handleDisableable_appIsEnabledAndInKeepEnabledWhitelist_buttonShouldNotWork() {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = "pkg";
info.enabled = true;
info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
appEntry.info = info;
final HashSet<String> packages = new HashSet<>();
packages.add(info.packageName);
when(mFeatureFactory.applicationFeatureProvider.getKeepEnabledPackages())
.thenReturn(packages);
assertThat(mController.handleDisableable(appEntry, mock(PackageInfo.class))).isFalse();
verify(mController.mActionButtons).setButton1Text(R.string.disable_text);
}
@Implements(Utils.class)
public static class ShadowUtils {
@Implementation
public static boolean isSystemPackage(Resources resources, PackageManager pm,
PackageInfo pkg) {
return false;
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.fuelgauge;
package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
@@ -44,6 +44,8 @@ import android.os.UserManager;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.appinfo.AppButtonsPreferenceController;
import com.android.settings.applications.appinfo.ButtonActionDialogFragment;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.ActionButtonPreferenceTest;
@@ -107,6 +109,7 @@ public class AppButtonsPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
FakeFeatureFactory.setupForTest();
doReturn(mDpm).when(mSettingsActivity).getSystemService(Context.DEVICE_POLICY_SERVICE);
doReturn(mUserManager).when(mSettingsActivity).getSystemService(Context.USER_SERVICE);
doReturn(mPackageManger).when(mSettingsActivity).getPackageManager();
doReturn(mAm).when(mSettingsActivity).getSystemService(Context.ACTIVITY_SERVICE);
@@ -115,8 +118,7 @@ public class AppButtonsPreferenceControllerTest {
when(mSettingsActivity.getResources().getString(anyInt())).thenReturn(RESOURCE_STRING);
mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment,
mLifecycle, PACKAGE_NAME, mState, mDpm, mUserManager, mPackageManger,
REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN));
mLifecycle, PACKAGE_NAME, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN));
doReturn(false).when(mController).isFallbackPackage(anyString());
mAppEntry.info = mAppInfo;
@@ -334,6 +336,15 @@ public class AppButtonsPreferenceControllerTest {
assertThat(controllable).isTrue();
}
@Test
public void handleActivityResult_packageUninstalled_shouldFinishPrefernecePanel() {
doReturn(false).when(mController).refreshUi();
mController.handleActivityResult(REQUEST_UNINSTALL, 0, mock(Intent.class));
verify(mSettingsActivity).finishPreferencePanel(anyInt(), any(Intent.class));
}
@Test
public void refreshUi_packageNull_shouldNotCrash() {
mController.mPackageName = null;
@@ -344,7 +355,7 @@ public class AppButtonsPreferenceControllerTest {
@Test
public void onPackageListChanged_available_shouldRefreshUi() {
doReturn(true).when(mController).isAvailable();
doReturn(mController.AVAILABLE).when(mController).getAvailabilityStatus();
doReturn(true).when(mController).refreshUi();
mController.onPackageListChanged();
@@ -354,7 +365,7 @@ public class AppButtonsPreferenceControllerTest {
@Test
public void onPackageListChanged_notAvailable_shouldNotRefreshUiAndNoCrash() {
doReturn(false).when(mController).isAvailable();
doReturn(mController.DISABLED_FOR_USER).when(mController).getAvailabilityStatus();
mController.onPackageListChanged();

View File

@@ -232,15 +232,6 @@ public final class AppInfoDashboardFragmentTest {
verify(mActivity).invalidateOptionsMenu();
}
@Test
public void onActivityResult_packageUninstalled_shouldFinishAndRemoveTask() {
doReturn(false).when(mFragment).refreshUi();
mFragment.onActivityResult(mFragment.REQUEST_UNINSTALL, 0, mock(Intent.class));
verify(mActivity).finishAndRemoveTask();
}
@Test
public void getPreferenceControllers_noPackageInfo_shouldReturnNull() {
doNothing().when(mFragment).retrieveAppEntry();

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
@@ -128,7 +128,7 @@ public class ButtonActionDialogFragmentTest {
/**
* Test fragment that used as the target fragment, it must implement the
* {@link com.android.settings.fuelgauge.ButtonActionDialogFragment.AppButtonsDialogListener}
* {@link ButtonActionDialogFragment.AppButtonsDialogListener}
*/
public static class TestFragment extends Fragment implements
ButtonActionDialogFragment.AppButtonsDialogListener {

View File

@@ -16,8 +16,6 @@
package com.android.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
@@ -25,20 +23,11 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.UserManager;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.DefaultAppInfo;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
@@ -85,39 +74,4 @@ public class DefaultBrowserPickerTest {
mPicker.getDefaultKey();
verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
}
@Test
public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final String PACKAGE_ONE = "com.first.package";
final String PACKAGE_TWO = "com.second.package";
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_ONE), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_ONE));
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_TWO), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_TWO));
final List<DefaultAppInfo> defaultBrowserInfo = mPicker.getCandidates();
assertThat(defaultBrowserInfo.size()).isEqualTo(2);
}
private ResolveInfo createResolveInfo(String packageName) {
final ResolveInfo info = new ResolveInfo();
info.handleAllWebDataURI = true;
info.activityInfo = new ActivityInfo();
info.activityInfo.packageName = packageName;
return info;
}
private ApplicationInfo createApplicationInfo(String packageName) {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
return info;
}
}

View File

@@ -17,15 +17,21 @@
package com.android.settings.applications.defaultapps;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
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;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.UserManager;
import androidx.preference.Preference;
@@ -33,6 +39,8 @@ import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,8 +81,11 @@ public class DefaultBrowserPreferenceControllerTest {
@Test
public void isAvailable_hasBrowser_shouldReturnTrue() {
final ResolveInfo info = new ResolveInfo();
info.activityInfo = new ActivityInfo();
info.handleAllWebDataURI = true;
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(Collections.singletonList(new ResolveInfo()));
.thenReturn(Collections.singletonList(info));
assertThat(mController.isAvailable()).isTrue();
}
@@ -88,6 +99,28 @@ public class DefaultBrowserPreferenceControllerTest {
verify(pref).setSummary(R.string.app_list_preference_none);
}
@Test
public void getDefaultAppLabel_hasAppWithMultipleResolvedInfo_shouldReturnLabel()
throws NameNotFoundException {
DefaultBrowserPreferenceController spyController = spy(mController);
doReturn(null).when(spyController).getDefaultAppIcon();
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final CharSequence PACKAGE_NAME = "com.test.package";
final ResolveInfo info1 = spy(createResolveInfo(PACKAGE_NAME.toString()));
when(info1.loadLabel(mPackageManager)).thenReturn(PACKAGE_NAME);
resolveInfos.add(info1);
resolveInfos.add(createResolveInfo(PACKAGE_NAME.toString()));
when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mPackageManager.getApplicationInfoAsUser(
eq(PACKAGE_NAME.toString()), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_NAME.toString()));
final Preference pref = mock(Preference.class);
assertThat(spyController.getDefaultAppLabel()).isEqualTo(PACKAGE_NAME);
}
@Test
public void getDefaultApp_shouldGetDefaultBrowserPackage() {
mController.getDefaultAppInfo();
@@ -103,4 +136,40 @@ public class DefaultBrowserPreferenceControllerTest {
assertThat(mController.isBrowserDefault("pkg", 0)).isTrue();
}
@Test
public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
final List<ResolveInfo> resolveInfos = new ArrayList<>();
final String PACKAGE_ONE = "com.first.package";
final String PACKAGE_TWO = "com.second.package";
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
resolveInfos.add(createResolveInfo(PACKAGE_ONE));
resolveInfos.add(createResolveInfo(PACKAGE_TWO));
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_ONE), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_ONE));
when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_TWO), anyInt(), anyInt()))
.thenReturn(createApplicationInfo(PACKAGE_TWO));
final List<ResolveInfo> defaultBrowserInfo =
mController.getCandidates(mPackageManager, 0 /* userId */);
assertThat(defaultBrowserInfo.size()).isEqualTo(2);
}
private ResolveInfo createResolveInfo(String packageName) {
final ResolveInfo info = new ResolveInfo();
info.handleAllWebDataURI = true;
info.activityInfo = new ActivityInfo();
info.activityInfo.packageName = packageName;
return info;
}
private ApplicationInfo createApplicationInfo(String packageName) {
final ApplicationInfo info = new ApplicationInfo();
info.packageName = packageName;
return info;
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -40,7 +40,7 @@ public class DataSaverControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mController = new DataSaverController(mContext);
mController = new DataSaverController(mContext, "key");
}
@Test

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -40,7 +40,7 @@ public class DeviceAdministratorsControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mController = new DeviceAdministratorsController(mContext);
mController = new DeviceAdministratorsController(mContext, "key");
}
@Test

View File

@@ -14,10 +14,9 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import android.content.Context;
@@ -26,31 +25,39 @@ import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(SettingsRobolectricTestRunner.class)
public class EnabledVrListenersControllerTest {
private Context mContext;
private EnabledVrListenersController mController;
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mController = new EnabledVrListenersController(mContext);
mContext = RuntimeEnvironment.application;
mController = new EnabledVrListenersController(mContext, "key");
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
}
@Test
public void testEnabledVrListeners_byDefault_shouldBeShown() {
public void isAvailable_byDefault_true() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_lowMemory_false() {
mActivityManager.setIsLowRamDevice(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
@Config(qualifiers = "mcc999")
public void testEnabledVrListeners_ifDisabled_shouldNotBeShown() {
public void isAvailable_disabled_false() {
assertThat(mController.isAvailable()).isFalse();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -40,7 +40,7 @@ public class HighPowerAppsControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mController = new HighPowerAppsController(mContext);
mController = new HighPowerAppsController(mContext, "key");
}
@Test

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -40,7 +40,7 @@ public class PremiumSmsControllerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
mController = new PremiumSmsController(mContext);
mController = new PremiumSmsController(mContext, "key");
}
@Test

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.specialaccess;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
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.shadow.api.Shadow;
import org.robolectric.shadows.ShadowActivityManager;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenAccessControllerTest {
private Context mContext;
private ZenAccessController mController;
private ShadowActivityManager mActivityManager;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new ZenAccessController(mContext, "key");
mActivityManager = Shadow.extract(mContext.getSystemService(Context.ACTIVITY_SERVICE));
}
@Test
public void isAvailable_byDefault_true() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_lowMemory_false() {
mActivityManager.setIsLowRamDevice(true);
assertThat(mController.isAvailable()).isTrue();
}
}

View File

@@ -203,6 +203,33 @@ public class AvailableMediaBluetoothDeviceUpdaterTest {
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_hearingAidDeviceConnected_notInCall_addPreference()
{
mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_hearingAidDeviceConnected_inCall_addPreference() {
mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_deviceDisconnected_removePreference() {
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,

View File

@@ -204,6 +204,34 @@ public class ConnectedBluetoothDeviceUpdaterTest {
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_hearingAidDeviceConnected_inCall_removePreference()
{
mShadowAudioManager.setMode(AudioManager.MODE_IN_CALL);
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_hearingAidDeviceConnected_notInCall_removePreference
() {
mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
when(mBluetoothDeviceUpdater.
isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isConnectedHearingAidDevice()).thenReturn(true);
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
}
@Test
public void onProfileConnectionStateChanged_deviceDisconnected_removePreference() {
mBluetoothDeviceUpdater.onProfileConnectionStateChanged(mCachedBluetoothDevice,

View File

@@ -67,7 +67,7 @@ public class BasePreferenceControllerSignatureInspector extends CodeInspector {
}
assertWithMessage("All BasePreferenceController (and subclasses) constructor must either"
+ "only take Context, or (Context, String). No other types are allowed")
+ " only take Context, or (Context, String). No other types are allowed")
.that(badClasses.toString())
.isEmpty();

View File

@@ -19,7 +19,10 @@ package com.android.settings.development.qstile;
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 android.content.ComponentName;
import android.content.pm.PackageManager;
import android.service.quicksettings.Tile;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -37,6 +40,9 @@ public class DevelopmentTilesTest {
@Mock
private Tile mTile;
@Mock
private PackageManager mPackageManager;
private DevelopmentTiles mService;
@Before
@@ -48,11 +54,18 @@ public class DevelopmentTilesTest {
@Test
public void refresh_devOptionIsDisabled_shouldResetTileValue() {
final ComponentName cn = new ComponentName(
mService.getPackageName(), mService.getClass().getName());
doReturn(mPackageManager).when(mService).getPackageManager();
DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(mService, false);
mService.setIsEnabled(true);
mService.refresh();
verify(mPackageManager).setComponentEnabledSetting(cn,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
assertThat(mService.isEnabled()).isFalse();
}
}

View File

@@ -19,6 +19,7 @@ import static com.android.settings.applications.manageapplications.ManageApplica
import static com.android.settings.applications.manageapplications.ManageApplications.EXTRA_WORK_ONLY;
import static com.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -123,7 +124,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mActivity).startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
verify(mActivity).startActivityForResultAsUser(argumentCaptor.capture(), anyInt(),
nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
@@ -140,8 +142,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity())
.startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
@@ -167,8 +169,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
@@ -186,8 +188,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity())
.startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
@@ -223,8 +225,8 @@ public class StorageItemPreferenceControllerTest {
.isTrue();
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
Intent browseIntent = mVolume.buildBrowseIntent();
@@ -240,8 +242,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);
@@ -258,8 +260,8 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mFragment.getActivity()).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
verify(mFragment.getActivity()).startActivityForResultAsUser(argumentCaptor.capture(),
anyInt(), nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_MAIN);

View File

@@ -18,6 +18,7 @@ package com.android.settings.fuelgauge.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import androidx.lifecycle.LifecycleOwner;
import android.content.Context;
import android.provider.Settings;
@@ -39,6 +40,7 @@ public class AutoBatterySeekBarPreferenceControllerTest {
private static final int TRIGGER_LEVEL = 20;
private static final int DEFAULT_LEVEL = 15;
private static final int INTERVAL = 5;
private AutoBatterySeekBarPreferenceController mController;
private Context mContext;
@@ -85,15 +87,16 @@ public class AutoBatterySeekBarPreferenceControllerTest {
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getTitle()).isEqualTo("At 20%");
assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL);
assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL / INTERVAL);
}
@Test
public void testOnPreferenceChange_updateValue() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
mController.onPreferenceChange(mPreference, TRIGGER_LEVEL);
mController.onPreferenceChange(mPreference, TRIGGER_LEVEL / INTERVAL);
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
@@ -106,7 +109,7 @@ public class AutoBatterySeekBarPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.getMax()).isEqualTo(50);
assertThat(mPreference.getMax()).isEqualTo(50 / INTERVAL);
}
@Test

View File

@@ -178,7 +178,7 @@ public class AnomalyDetectionJobServiceTest {
verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
MetricsProto.MetricsEvent.ACTION_ANOMALY_IGNORED,
SYSTEM_PACKAGE,
Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, ANOMALY_TYPE),
Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, ANOMALY_TYPE),
Pair.create(MetricsProto.MetricsEvent.FIELD_APP_VERSION_CODE, VERSION_CODE));
}

View File

@@ -18,11 +18,12 @@ package com.android.settings.nfc;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.nfc.NfcAdapter;
import android.provider.Settings;
import androidx.preference.Preference;
import android.provider.Settings.Global;
import androidx.preference.SwitchPreference;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -52,8 +53,8 @@ public class NfcAirplaneModeObserverTest {
mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
mNfcAirplaneModeObserver = new NfcAirplaneModeObserver(mContext, mNfcAdapter,
(Preference) mNfcPreference);
mNfcAirplaneModeObserver =
new NfcAirplaneModeObserver(mContext, mNfcAdapter, mNfcPreference);
}
@Test
@@ -67,20 +68,51 @@ public class NfcAirplaneModeObserverTest {
NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcAdapter.isEnabled()).isFalse();
}
@Test
public void NfcAirplaneModeObserver_airplaneModeOnNfcToggleable_shouldEnablePreference() {
ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 0);
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcPreference.isEnabled()).isTrue();
}
@Test
public void NfcAirplaneModeObserver_airplaneModeOnNfcNotToggleable_shouldDisablePreference() {
ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 0);
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Global.RADIO_WIFI);
mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcPreference.isEnabled()).isFalse();
}
@Test
public void NfcAirplaneModeObserver_airplaneOff_shouldEnableNfc() {
ReflectionHelpers.setField(mNfcAirplaneModeObserver,
"mAirplaneMode", 1);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0);
public void NfcAirplaneModeObserver_airplaneModeOff_shouldEnablePreference() {
ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 1);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
mNfcAirplaneModeObserver.onChange(false,
NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcAdapter.isEnabled()).isTrue();
assertThat(mNfcPreference.isEnabled()).isTrue();
}
@Test
public void NfcAirplaneModeObserver_airplaneModeOff_shouldNotEnableNfcAutomatically() {
ReflectionHelpers.setField(mNfcAirplaneModeObserver, "mAirplaneMode", 1);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
mNfcAirplaneModeObserver.onChange(false, NfcAirplaneModeObserver.AIRPLANE_MODE_URI);
assertThat(mNfcAdapter.isEnabled()).isFalse();
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.nfc;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.Context;
import android.nfc.NfcAdapter;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
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;
@RunWith(SettingsRobolectricTestRunner.class)
public class NfcEnablerTest {
@Mock
private SwitchPreference mNfcPreference;
private Context mContext;
private NfcEnabler mNfcEnabler;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mNfcEnabler = spy(new NfcEnabler(mContext, mNfcPreference));
}
@Test
public void isToggleable_AirplaneModeOff_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcNotInAirplaneModeRadio_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver, Settings.Global.AIRPLANE_MODE_RADIOS, "");
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcToggleable_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcNotToggleable_shouldReturnFalse() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
assertThat(mNfcEnabler.isToggleable()).isFalse();
}
@Test
public void handleNfcStateChanged_stateOff_shouldCheckIfPreferenceEnableState() {
mNfcEnabler.handleNfcStateChanged(NfcAdapter.STATE_OFF);
verify(mNfcEnabler).isToggleable();
}
}

View File

@@ -75,15 +75,6 @@ public class NfcPreferenceControllerTest {
mNfcPreference = new SwitchPreference(RuntimeEnvironment.application);
when(mScreen.findPreference(mNfcController.getPreferenceKey())).thenReturn(mNfcPreference);
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
Settings.Global.RADIO_NFC);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON,
0);
mNfcController.displayPreference(mScreen);
}
@Test
@@ -102,6 +93,7 @@ public class NfcPreferenceControllerTest {
@Test
public void isNfcEnable_nfcStateNotTurning_shouldReturnTrue() {
mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isEnabled()).isTrue();
@@ -113,6 +105,7 @@ public class NfcPreferenceControllerTest {
@Test
public void isNfcEnable_nfcStateTurning_shouldReturnFalse() {
mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isEnabled()).isFalse();
@@ -124,6 +117,7 @@ public class NfcPreferenceControllerTest {
@Test
public void isNfcChecked_nfcStateOn_shouldReturnTrue() {
mNfcController.displayPreference(mScreen);
when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON);
mNfcController.onResume();
assertThat(mNfcPreference.isChecked()).isTrue();
@@ -205,4 +199,52 @@ public class NfcPreferenceControllerTest {
assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse();
}
@Test
public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosContainsNfc_shouldReturnTrue() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isTrue();
}
@Test
public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosWithoutNfc_shouldReturnFalse() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, "");
assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isFalse();
}
@Test
public void displayPreference_airplaneModeRadiosContainsNfc_shouldCreateAirplaneModeObserver() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
mNfcController.displayPreference(mScreen);
assertThat(mNfcController.mAirplaneModeObserver).isNotNull();
}
@Test
public void displayPreference_nfcToggleableInAirplaneMode_shouldCreateAirplaneModeObserver() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
mNfcController.displayPreference(mScreen);
assertThat(mNfcController.mAirplaneModeObserver).isNotNull();
}
@Test
public void displayPreference_nfcNotAffectByAirplaneMode_shouldNotCreateAirplaneModeObserver() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, "");
mNfcController.displayPreference(mScreen);
assertThat(mNfcController.mAirplaneModeObserver).isNull();
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.password;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
import android.app.Activity;
import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SettingsRobolectricTestRunner.class)
public class ChooseLockGenericTest {
@Test
public void onActivityResult_nullIntentData_shouldNotCrash() {
ChooseLockGenericFragment fragment = spy(new ChooseLockGenericFragment());
doNothing().when(fragment).updatePreferencesOrFinish(anyBoolean());
fragment.onActivityResult(
fragment.CONFIRM_EXISTING_REQUEST, Activity.RESULT_OK, null /* data */);
// no crash
}
}