Snap for 4842501 from f350fa875b to qt-release
Change-Id: Ic753ba0535be15974d9a5aad119027b5e30878e3
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
106
tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
Normal file
106
tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user