Add controllers for default app shortcut preferences.

- add the default app shortcut preferences to the preference screen
xml instead of creating them dynamically in the fragment.
- add controller for each of the shortcut preference.
- move the corresponding shortcut detail settings into the appinfo
package.
- add individual preference screen xml for the shortcut detail settings
instead of using the shared screen template.

Bug: 69384089
Test: make RunSettingsRoboTests
Change-Id: I7bc0b3b727e87fb1a32a82291e64b8e290947671
This commit is contained in:
Doris Ling
2017-12-01 17:18:01 -08:00
parent d7d5754cfd
commit 765007b0bf
28 changed files with 961 additions and 211 deletions

View File

@@ -105,6 +105,33 @@
android:title="@string/sms_application_title" android:title="@string/sms_application_title"
android:summary="@string/summary_placeholder" /> android:summary="@string/summary_placeholder" />
<!-- Advanced apps settings -->
<PreferenceCategory
android:key="advanced_app_info"
android:title="@string/advanced_apps">
<Preference
android:key="system_alert_window"
android:title="@string/draw_overlay"
android:summary="@string/summary_placeholder" />
<Preference
android:key="write_settings_apps"
android:title="@string/write_settings"
android:summary="@string/summary_placeholder" />
<Preference
android:key="picture_in_picture"
android:title="@string/picture_in_picture_app_detail_title"
android:summary="@string/summary_placeholder" />
<Preference
android:key="install_other_apps"
android:title="@string/install_other_apps"
android:summary="@string/summary_placeholder" />
</PreferenceCategory>
<Preference <Preference
android:key="app_version" android:key="app_version"
android:selectable="false" android:selectable="false"

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="draw_overlay_permission_detail_settings"
android:title="@string/draw_overlay">
<SwitchPreference
android:key="app_ops_settings_switch"
android:title="@string/permit_draw_overlay"/>
<Preference
android:key="app_ops_settings_preference"
android:title="@string/app_overlay_permission_preference"/>
<Preference
android:summary="@string/allow_overlay_description"
android:selectable="false"/>
</PreferenceScreen>

View File

@@ -15,7 +15,6 @@
--> -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/install_other_apps"> android:title="@string/install_other_apps">
<com.android.settingslib.RestrictedSwitchPreference <com.android.settingslib.RestrictedSwitchPreference

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="picture_in_picture_permission_detail_settings"
android:title="@string/picture_in_picture_app_detail_title">
<SwitchPreference
android:key="app_ops_settings_switch"
android:title="@string/picture_in_picture_app_detail_switch"/>
<Preference
android:summary="@string/picture_in_picture_app_detail_summary"
android:selectable="false"/>
</PreferenceScreen>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="write_system_settings_permission_detail_settings"
android:title="@string/write_settings">
<SwitchPreference
android:key="app_ops_settings_switch"
android:title="@string/permit_write_settings"/>
<Preference
android:key="app_ops_settings_preference"
android:title="@string/write_settings_preference"/>
<Preference
android:summary="@string/write_settings_description"
android:selectable="false"/>
</PreferenceScreen>

View File

@@ -18,7 +18,6 @@ package com.android.settings.applications;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.Manifest.permission;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.AlertDialog; import android.app.AlertDialog;
@@ -47,7 +46,6 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceCategory; import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils; import android.text.TextUtils;
@@ -58,7 +56,6 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.webkit.IWebViewUpdateService; import android.webkit.IWebViewUpdateService;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.DeviceAdminAdd; import com.android.settings.DeviceAdminAdd;
import com.android.settings.R; import com.android.settings.R;
@@ -78,11 +75,10 @@ import com.android.settings.applications.appinfo.DefaultEmergencyShortcutPrefere
import com.android.settings.applications.appinfo.DefaultHomeShortcutPreferenceController; import com.android.settings.applications.appinfo.DefaultHomeShortcutPreferenceController;
import com.android.settings.applications.appinfo.DefaultPhoneShortcutPreferenceController; import com.android.settings.applications.appinfo.DefaultPhoneShortcutPreferenceController;
import com.android.settings.applications.appinfo.DefaultSmsShortcutPreferenceController; import com.android.settings.applications.appinfo.DefaultSmsShortcutPreferenceController;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController; import com.android.settings.applications.appinfo.DrawOverlayDetailPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController; import com.android.settings.applications.appinfo.ExternalSourceDetailPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController; import com.android.settings.applications.appinfo.PictureInPictureDetailPreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController; import com.android.settings.applications.appinfo.WriteSystemSettingsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.instantapps.InstantAppButtonsController; import com.android.settings.applications.instantapps.InstantAppButtonsController;
import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
@@ -90,6 +86,7 @@ import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settings.wrapper.DevicePolicyManagerWrapper; import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils; import com.android.settingslib.applications.AppUtils;
@@ -97,7 +94,6 @@ import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
@@ -149,6 +145,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
public static final String ARG_PACKAGE_UID = "uid"; public static final String ARG_PACKAGE_UID = "uid";
protected static final boolean localLOGV = false; protected static final boolean localLOGV = false;
private static final String KEY_ADVANCED_APP_INFO_CATEGORY = "advanced_app_info";
private EnforcedAdmin mAppsControlDisallowedAdmin; private EnforcedAdmin mAppsControlDisallowedAdmin;
private boolean mAppsControlDisallowedBySystem; private boolean mAppsControlDisallowedBySystem;
@@ -358,11 +355,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
if (!refreshUi()) { if (!refreshUi()) {
setIntentAndFinish(true, true); setIntentAndFinish(true, true);
} }
if (mFinishing) {
return;
}
updateDynamicPrefs();
} }
@Override @Override
@@ -404,6 +396,17 @@ public class AppInfoDashboardFragment extends DashboardFragment
controllers.add(new DefaultEmergencyShortcutPreferenceController(context, packageName)); controllers.add(new DefaultEmergencyShortcutPreferenceController(context, packageName));
controllers.add(new DefaultSmsShortcutPreferenceController(context, packageName)); controllers.add(new DefaultSmsShortcutPreferenceController(context, packageName));
final List<AbstractPreferenceController> advancedAppInfoControllers = new ArrayList<>();
advancedAppInfoControllers.add(new DrawOverlayDetailPreferenceController(context, this));
advancedAppInfoControllers.add(new WriteSystemSettingsPreferenceController(context, this));
advancedAppInfoControllers.add(
new PictureInPictureDetailPreferenceController(context, this, packageName));
advancedAppInfoControllers.add(
new ExternalSourceDetailPreferenceController(context, this, packageName));
controllers.addAll(advancedAppInfoControllers);
controllers.add(new PreferenceCategoryController(
context, KEY_ADVANCED_APP_INFO_CATEGORY, advancedAppInfoControllers));
return controllers; return controllers;
} }
@@ -415,6 +418,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
} }
public PackageInfo getPackageInfo() { public PackageInfo getPackageInfo() {
if (mAppEntry == null) {
retrieveAppEntry();
}
return mPackageInfo; return mPackageInfo;
} }
@@ -603,7 +609,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
return false; return false;
} }
protected boolean refreshUi() { @VisibleForTesting
boolean refreshUi() {
retrieveAppEntry(); retrieveAppEntry();
if (mAppEntry == null) { if (mAppEntry == null) {
return false; // onCreate must have failed, make sure to exit return false; // onCreate must have failed, make sure to exit
@@ -782,10 +789,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
} }
} }
private void startAppInfoFragment(Class<?> fragment, int title) {
startAppInfoFragment(fragment, title, this, mAppEntry);
}
public static void startAppInfoFragment(Class<?> fragment, int title, public static void startAppInfoFragment(Class<?> fragment, int title,
SettingsPreferenceFragment caller, AppEntry appEntry) { SettingsPreferenceFragment caller, AppEntry appEntry) {
// start new fragment to display extended information // start new fragment to display extended information
@@ -871,100 +874,10 @@ public class AppInfoDashboardFragment extends DashboardFragment
if (UserManager.get(getContext()).isManagedProfile()) { if (UserManager.get(getContext()).isManagedProfile()) {
return; return;
} }
final PreferenceScreen screen = getPreferenceScreen(); addAppInstallerInfoPref(getPreferenceScreen());
final Context context = getContext();
// Get the package info with the activities
PackageInfo packageInfoWithActivities = null;
try {
packageInfoWithActivities = mPm.getPackageInfoAsUser(mPackageName,
PackageManager.GET_ACTIVITIES, UserHandle.myUserId());
} catch (NameNotFoundException e) {
Log.e(TAG, "Exception while retrieving the package info of " + mPackageName, e);
}
boolean hasDrawOverOtherApps = hasPermission(permission.SYSTEM_ALERT_WINDOW);
boolean hasWriteSettings = hasPermission(permission.WRITE_SETTINGS);
boolean hasPictureInPictureActivities = (packageInfoWithActivities != null) &&
PictureInPictureSettings.checkPackageHasPictureInPictureActivities(
packageInfoWithActivities.packageName,
packageInfoWithActivities.activities);
boolean isPotentialAppSource = isPotentialAppSource();
if (hasDrawOverOtherApps || hasWriteSettings || hasPictureInPictureActivities ||
isPotentialAppSource) {
PreferenceCategory category = new PreferenceCategory(getPrefContext());
category.setTitle(R.string.advanced_apps);
screen.addPreference(category);
if (hasDrawOverOtherApps) {
Preference pref = new Preference(getPrefContext());
pref.setTitle(R.string.draw_overlay);
pref.setKey("system_alert_window");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startAppInfoFragment(DrawOverlayDetails.class, R.string.draw_overlay);
return true;
}
});
category.addPreference(pref);
}
if (hasWriteSettings) {
Preference pref = new Preference(getPrefContext());
pref.setTitle(R.string.write_settings);
pref.setKey("write_settings_apps");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startAppInfoFragment(WriteSettingsDetails.class, R.string.write_settings);
return true;
}
});
category.addPreference(pref);
}
if (hasPictureInPictureActivities) {
Preference pref = new Preference(getPrefContext());
pref.setTitle(R.string.picture_in_picture_app_detail_title);
pref.setKey("picture_in_picture");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
AppInfoBase.startAppInfoFragment(PictureInPictureDetails.class,
R.string.picture_in_picture_app_detail_title, mPackageName,
mPackageInfo.applicationInfo.uid, AppInfoDashboardFragment.this,
-1, getMetricsCategory());
return true;
}
});
category.addPreference(pref);
}
if (isPotentialAppSource) {
Preference pref = new Preference(getPrefContext());
pref.setTitle(R.string.install_other_apps);
pref.setKey("install_other_apps");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
startAppInfoFragment(ExternalSourcesDetails.class,
R.string.install_other_apps);
return true;
}
});
category.addPreference(pref);
}
}
addAppInstallerInfoPref(screen);
maybeAddInstantAppButtons(); maybeAddInstantAppButtons();
} }
private boolean isPotentialAppSource() {
AppStateInstallAppsBridge.InstallAppsState appState =
new AppStateInstallAppsBridge(getContext(), null, null)
.createInstallAppsStateFor(mPackageName, mPackageInfo.applicationInfo.uid);
return appState.isPotentialAppSource();
}
private void addAppInstallerInfoPref(PreferenceScreen screen) { private void addAppInstallerInfoPref(PreferenceScreen screen) {
String installerPackageName = String installerPackageName =
AppStoreUtil.getInstallerPackageName(getContext(), mPackageName); AppStoreUtil.getInstallerPackageName(getContext(), mPackageName);
@@ -1008,39 +921,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
} }
} }
private boolean hasPermission(String permission) {
if (mPackageInfo == null || mPackageInfo.requestedPermissions == null) {
return false;
}
for (int i = 0; i < mPackageInfo.requestedPermissions.length; i++) {
if (mPackageInfo.requestedPermissions[i].equals(permission)) {
return true;
}
}
return false;
}
private void updateDynamicPrefs() {
final Context context = getContext();
Preference pref = findPreference("system_alert_window");
if (pref != null) {
pref.setSummary(DrawOverlayDetails.getSummary(getContext(), mAppEntry));
}
pref = findPreference("picture_in_picture");
if (pref != null) {
pref.setSummary(PictureInPictureDetails.getPreferenceSummary(getContext(),
mPackageInfo.applicationInfo.uid, mPackageName));
}
pref = findPreference("write_settings_apps");
if (pref != null) {
pref.setSummary(WriteSettingsDetails.getSummary(getContext(), mAppEntry));
}
pref = findPreference("install_other_apps");
if (pref != null) {
pref.setSummary(ExternalSourcesDetails.getPreferenceSummary(getContext(), mAppEntry));
}
}
private void onPackageRemoved() { private void onPackageRemoved() {
getActivity().finishActivity(SUB_INFO_FRAGMENT); getActivity().finishActivity(SUB_INFO_FRAGMENT);
getActivity().finishAndRemoveTask(); getActivity().finishAndRemoveTask();
@@ -1112,7 +992,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
return mPackageName; return mPackageName;
} }
final Bundle args = getArguments(); final Bundle args = getArguments();
String mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; mPackageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
if (mPackageName == null) { if (mPackageName == null) {
Intent intent = (args == null) ? Intent intent = (args == null) ?
getActivity().getIntent() : (Intent) args.getParcelable("intent"); getActivity().getIntent() : (Intent) args.getParcelable("intent");
@@ -1229,7 +1109,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
@Override @Override
public int getMetricsCategory() { public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_APP_INFO_ACTION; return MetricsEvent.DIALOG_APP_INFO_ACTION;
} }
@Override @Override

View File

@@ -90,7 +90,7 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName); return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName);
} }
InstallAppsState createInstallAppsStateFor(String packageName, int uid) { public InstallAppsState createInstallAppsStateFor(String packageName, int uid) {
final InstallAppsState appState = new InstallAppsState(); final InstallAppsState appState = new InstallAppsState();
appState.permissionRequested = hasRequestedAppOpPermission( appState.permissionRequested = hasRequestedAppOpPermission(
Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName); Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName);

View File

@@ -75,6 +75,11 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment; import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.PictureInPictureDetails;
import com.android.settings.applications.appinfo.PictureInPictureSettings;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController; import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController; import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController; import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;

View File

@@ -0,0 +1,70 @@
/*
* 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 android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppInfoDashboardFragment;
public class DrawOverlayDetailPreferenceController extends AppInfoPreferenceControllerBase {
private static final String KEY = "system_alert_window";
public DrawOverlayDetailPreferenceController(Context context, AppInfoDashboardFragment parent) {
super(context, parent, KEY);
}
@Override
public int getAvailabilityStatus() {
if (UserManager.get(mContext).isManagedProfile()) {
return DISABLED_FOR_USER;
}
final PackageInfo packageInfo = mParent.getPackageInfo();
if (packageInfo == null || packageInfo.requestedPermissions == null) {
return DISABLED_FOR_USER;
}
for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
if (packageInfo.requestedPermissions[i].equals(SYSTEM_ALERT_WINDOW)) {
return AVAILABLE;
}
}
return DISABLED_FOR_USER;
}
@Override
public void updateState(Preference preference) {
preference.setSummary(getSummary());
}
@Override
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
return DrawOverlayDetails.class;
}
@VisibleForTesting
CharSequence getSummary() {
return DrawOverlayDetails.getSummary(mContext, mParent.getAppEntry());
}
}

View File

@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
@@ -29,12 +31,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener; import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log; import android.util.Log;
import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateOverlayBridge;
import com.android.settings.applications.AppStateOverlayBridge.OverlayState; import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -44,7 +47,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference";
private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description";
private static final String LOG_TAG = "DrawOverlayDetails"; private static final String LOG_TAG = "DrawOverlayDetails";
private static final int [] APP_OPS_OP_CODE = { private static final int [] APP_OPS_OP_CODE = {
@@ -57,7 +59,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
private AppOpsManager mAppOpsManager; private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref; private SwitchPreference mSwitchPref;
private Preference mOverlayPrefs; private Preference mOverlayPrefs;
private Preference mOverlayDesc;
private Intent mSettingsIntent; private Intent mSettingsIntent;
private OverlayState mOverlayState; private OverlayState mOverlayState;
@@ -70,16 +71,9 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
// find preferences // find preferences
addPreferencesFromResource(R.xml.app_ops_permissions_details); addPreferencesFromResource(R.xml.draw_overlay_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
mOverlayPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS); mOverlayPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS);
mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
// set title/summary for all of them
getPreferenceScreen().setTitle(R.string.draw_overlay);
mSwitchPref.setTitle(R.string.permit_draw_overlay);
mOverlayPrefs.setTitle(R.string.app_overlay_permission_preference);
mOverlayDesc.setSummary(R.string.allow_overlay_description);
// install event listeners // install event listeners
mSwitchPref.setOnPreferenceChangeListener(this); mSwitchPref.setOnPreferenceChangeListener(this);
@@ -116,7 +110,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
try { try {
getActivity().startActivityAsUser(mSettingsIntent, new UserHandle(mUserId)); getActivity().startActivityAsUser(mSettingsIntent, new UserHandle(mUserId));
} catch (ActivityNotFoundException e) { } catch (ActivityNotFoundException e) {
Log.w(LOG_TAG, "Unable to launch app draw overlay settings " + mSettingsIntent, e); Log.w(LOG_TAG, "Unable to launch app draw overlay settings " + mSettingsIntent,
e);
} }
} }
return true; return true;
@@ -161,7 +156,14 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
// you cannot ask a user to grant you a permission you did not have! // you cannot ask a user to grant you a permission you did not have!
mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled); mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled);
mOverlayPrefs.setEnabled(isAllowed); mOverlayPrefs.setEnabled(isAllowed);
ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
PackageManager.GET_META_DATA, mUserId);
if (resolveInfo == null) {
if (findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) {
getPreferenceScreen().removePreference(mOverlayPrefs); getPreferenceScreen().removePreference(mOverlayPrefs);
}
}
return true; return true;
} }

View File

@@ -0,0 +1,71 @@
/*
* 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.content.Context;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.applications.AppStateInstallAppsBridge;
public class ExternalSourceDetailPreferenceController extends AppInfoPreferenceControllerBase {
private static final String KEY = "install_other_apps";
private final String mPackageName;
public ExternalSourceDetailPreferenceController(Context context,
AppInfoDashboardFragment parent, String packageName) {
super(context, parent, KEY);
mPackageName = packageName;
}
@Override
public int getAvailabilityStatus() {
if (UserManager.get(mContext).isManagedProfile()) {
return DISABLED_FOR_USER;
}
return isPotentialAppSource() ? AVAILABLE : DISABLED_FOR_USER;
}
@Override
public void updateState(Preference preference) {
preference.setSummary(getPreferenceSummary());
}
@Override
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
return ExternalSourcesDetails.class;
}
@VisibleForTesting
CharSequence getPreferenceSummary() {
return ExternalSourcesDetails.getPreferenceSummary(mContext, mParent.getAppEntry());
}
@VisibleForTesting
boolean isPotentialAppSource() {
AppStateInstallAppsBridge.InstallAppsState appState =
new AppStateInstallAppsBridge(mContext, null, null).createInstallAppsStateFor(
mPackageName, mParent.getPackageInfo().applicationInfo.uid);
return appState.isPotentialAppSource();
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static android.app.Activity.RESULT_CANCELED; import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@@ -30,6 +30,8 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Settings; import com.android.settings.Settings;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateInstallAppsBridge;
import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState; import com.android.settings.applications.AppStateInstallAppsBridge.InstallAppsState;
import com.android.settingslib.RestrictedSwitchPreference; import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;

View File

@@ -0,0 +1,86 @@
/*
* 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.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppInfoDashboardFragment;
public class PictureInPictureDetailPreferenceController extends AppInfoPreferenceControllerBase {
private static final String KEY = "picture_in_picture";
private static final String TAG = "PicInPicDetailControl";
private final PackageManager mPackageManager;
private final String mPackageName;
public PictureInPictureDetailPreferenceController(Context context,
AppInfoDashboardFragment parent, String packageName) {
super(context, parent, KEY);
mPackageManager = context.getPackageManager();
mPackageName = packageName;
}
@Override
public int getAvailabilityStatus() {
if (UserManager.get(mContext).isManagedProfile()) {
return DISABLED_FOR_USER;
}
return hasPictureInPictureActivites() ? AVAILABLE : DISABLED_FOR_USER;
}
@Override
public void updateState(Preference preference) {
preference.setSummary(getPreferenceSummary());
}
@Override
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
return PictureInPictureDetails.class;
}
@VisibleForTesting
boolean hasPictureInPictureActivites() {
// Get the package info with the activities
PackageInfo packageInfoWithActivities = null;
try {
packageInfoWithActivities = mPackageManager.getPackageInfoAsUser(mPackageName,
PackageManager.GET_ACTIVITIES, UserHandle.myUserId());
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Exception while retrieving the package info of " + mPackageName, e);
}
return packageInfoWithActivities != null
&& PictureInPictureSettings.checkPackageHasPictureInPictureActivities(
packageInfoWithActivities.packageName,
packageInfoWithActivities.activities);
}
@VisibleForTesting
int getPreferenceSummary() {
return PictureInPictureDetails.getPreferenceSummary(mContext,
mParent.getPackageInfo().applicationInfo.uid, mPackageName);
}
}

View File

@@ -13,14 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference; import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener; import android.support.v7.preference.Preference.OnPreferenceChangeListener;
@@ -28,6 +26,7 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -38,42 +37,31 @@ public class PictureInPictureDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener { implements OnPreferenceChangeListener {
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference";
private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description";
private static final String LOG_TAG = "PictureInPictureDetails"; private static final String LOG_TAG = "PictureInPictureDetails";
private SwitchPreference mSwitchPref; private SwitchPreference mSwitchPref;
private Preference mOverlayDesc;
private Intent mSettingsIntent;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// find preferences // find preferences
addPreferencesFromResource(R.xml.app_ops_permissions_details); addPreferencesFromResource(R.xml.picture_in_picture_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
getPreferenceScreen().removePreference(findPreference(KEY_APP_OPS_SETTINGS_PREFS));
// set title/summary for all of them // set title/summary for all of them
getPreferenceScreen().setTitle(R.string.picture_in_picture_app_detail_title);
mSwitchPref.setTitle(R.string.picture_in_picture_app_detail_switch); mSwitchPref.setTitle(R.string.picture_in_picture_app_detail_switch);
mOverlayDesc.setSummary(R.string.picture_in_picture_app_detail_summary);
// install event listeners // install event listeners
mSwitchPref.setOnPreferenceChangeListener(this); mSwitchPref.setOnPreferenceChangeListener(this);
mSettingsIntent = new Intent(Intent.ACTION_MAIN)
.setAction(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS);
} }
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mSwitchPref) { if (preference == mSwitchPref) {
logSpecialPermissionChange((Boolean) newValue, mPackageName); logSpecialPermissionChange((Boolean) newValue, mPackageName);
setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid, mPackageName, setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid,
(Boolean) newValue); mPackageName, (Boolean) newValue);
return true; return true;
} }
return false; return false;
@@ -121,7 +109,7 @@ public class PictureInPictureDetails extends AppInfoWithHeader
* @return the summary for the current state of whether the app associated with the given * @return the summary for the current state of whether the app associated with the given
* {@param packageName} is allowed to enter picture-in-picture. * {@param packageName} is allowed to enter picture-in-picture.
*/ */
static int getPreferenceSummary(Context context, int uid, String packageName) { public static int getPreferenceSummary(Context context, int uid, String packageName) {
final boolean enabled = PictureInPictureDetails.getEnterPipStateForPackage(context, uid, final boolean enabled = PictureInPictureDetails.getEnterPipStateForPackage(context, uid,
packageName); packageName);
return enabled ? R.string.app_permission_summary_allowed return enabled ? R.string.app_permission_summary_allowed

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static android.content.pm.PackageManager.GET_ACTIVITIES; import static android.content.pm.PackageManager.GET_ACTIVITIES;
@@ -37,6 +37,7 @@ import android.view.View;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.notification.EmptyTextSettings; import com.android.settings.notification.EmptyTextSettings;
import com.android.settings.widget.AppPreference; import com.android.settings.widget.AppPreference;
import com.android.settings.wrapper.ActivityInfoWrapper; import com.android.settings.wrapper.ActivityInfoWrapper;
@@ -95,7 +96,7 @@ public class PictureInPictureSettings extends EmptyTextSettings {
* @return true if the package has any activities that declare that they support * @return true if the package has any activities that declare that they support
* picture-in-picture. * picture-in-picture.
*/ */
static boolean checkPackageHasPictureInPictureActivities(String packageName, public static boolean checkPackageHasPictureInPictureActivities(String packageName,
ActivityInfo[] activities) { ActivityInfo[] activities) {
ActivityInfoWrapper[] wrappedActivities = null; ActivityInfoWrapper[] wrappedActivities = null;
if (activities != null) { if (activities != null) {

View File

@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
@@ -31,7 +33,9 @@ import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState; import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettingsState; import com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettingsState;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
@@ -42,7 +46,6 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
private static final String KEY_APP_OPS_PREFERENCE_SCREEN = "app_ops_preference_screen"; private static final String KEY_APP_OPS_PREFERENCE_SCREEN = "app_ops_preference_screen";
private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch";
private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference";
private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description";
private static final String LOG_TAG = "WriteSettingsDetails"; private static final String LOG_TAG = "WriteSettingsDetails";
private static final int [] APP_OPS_OP_CODE = { private static final int [] APP_OPS_OP_CODE = {
@@ -55,7 +58,6 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
private AppOpsManager mAppOpsManager; private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref; private SwitchPreference mSwitchPref;
private Preference mWriteSettingsPrefs; private Preference mWriteSettingsPrefs;
private Preference mWriteSettingsDesc;
private Intent mSettingsIntent; private Intent mSettingsIntent;
private WriteSettingsState mWriteSettingsState; private WriteSettingsState mWriteSettingsState;
@@ -67,15 +69,9 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
mAppBridge = new AppStateWriteSettingsBridge(context, mState, null); mAppBridge = new AppStateWriteSettingsBridge(context, mState, null);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
addPreferencesFromResource(R.xml.app_ops_permissions_details); addPreferencesFromResource(R.xml.write_system_settings_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
mWriteSettingsPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS); mWriteSettingsPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS);
mWriteSettingsDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
getPreferenceScreen().setTitle(R.string.write_settings);
mSwitchPref.setTitle(R.string.permit_write_settings);
mWriteSettingsPrefs.setTitle(R.string.write_settings_preference);
mWriteSettingsDesc.setSummary(R.string.write_settings_description);
mSwitchPref.setOnPreferenceChangeListener(this); mSwitchPref.setOnPreferenceChangeListener(this);
mWriteSettingsPrefs.setOnPreferenceClickListener(this); mWriteSettingsPrefs.setOnPreferenceClickListener(this);
@@ -147,9 +143,14 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
// you can't ask a user for a permission you didn't even declare! // you can't ask a user for a permission you didn't even declare!
mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared); mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared);
mWriteSettingsPrefs.setEnabled(canWrite); mWriteSettingsPrefs.setEnabled(canWrite);
ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
PackageManager.GET_META_DATA, mUserId);
if (resolveInfo == null) {
if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) { if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) {
getPreferenceScreen().removePreference(mWriteSettingsPrefs); getPreferenceScreen().removePreference(mWriteSettingsPrefs);
} }
}
return true; return true;
} }

View File

@@ -0,0 +1,71 @@
/*
* 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 android.Manifest.permission.WRITE_SETTINGS;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.AppInfoDashboardFragment;
public class WriteSystemSettingsPreferenceController extends AppInfoPreferenceControllerBase {
private static final String KEY = "write_settings_apps";
public WriteSystemSettingsPreferenceController(Context context,
AppInfoDashboardFragment parent) {
super(context, parent, KEY);
}
@Override
public int getAvailabilityStatus() {
if (UserManager.get(mContext).isManagedProfile()) {
return DISABLED_FOR_USER;
}
final PackageInfo packageInfo = mParent.getPackageInfo();
if (packageInfo == null || packageInfo.requestedPermissions == null) {
return DISABLED_FOR_USER;
}
for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
if (packageInfo.requestedPermissions[i].equals(WRITE_SETTINGS)) {
return AVAILABLE;
}
}
return DISABLED_FOR_USER;
}
@Override
public void updateState(Preference preference) {
preference.setSummary(getSummary());
}
@Override
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
return WriteSettingsDetails.class;
}
@VisibleForTesting
CharSequence getSummary() {
return WriteSettingsDetails.getSummary(mContext, mParent.getAppEntry());
}
}

View File

@@ -89,14 +89,14 @@ import com.android.settings.applications.AppStateUsageBridge.UsageState;
import com.android.settings.applications.AppStateWriteSettingsBridge; import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.applications.AppStorageSettings; import com.android.settings.applications.AppStorageSettings;
import com.android.settings.applications.DefaultAppSettings; import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.applications.DrawOverlayDetails;
import com.android.settings.applications.ExternalSourcesDetails;
import com.android.settings.applications.InstalledAppCounter; import com.android.settings.applications.InstalledAppCounter;
import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.NotificationApps; import com.android.settings.applications.NotificationApps;
import com.android.settings.applications.UsageAccessDetails; import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.applications.AppInfoDashboardFragment; import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.core.FeatureFlags; import com.android.settings.core.FeatureFlags;
import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.dashboard.SummaryLoader; import com.android.settings.dashboard.SummaryLoader;

View File

@@ -40,19 +40,19 @@ import com.android.settings.accounts.ManagedProfileSettings;
import com.android.settings.accounts.UserAndAccountDashboardFragment; import com.android.settings.accounts.UserAndAccountDashboardFragment;
import com.android.settings.applications.AppAndNotificationDashboardFragment; import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.DefaultAppSettings; import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.applications.DrawOverlayDetails;
import com.android.settings.applications.ExternalSourcesDetails;
import com.android.settings.applications.InstalledAppDetails; import com.android.settings.applications.InstalledAppDetails;
import com.android.settings.applications.ManageDomainUrls; import com.android.settings.applications.ManageDomainUrls;
import com.android.settings.applications.NotificationApps; import com.android.settings.applications.NotificationApps;
import com.android.settings.applications.PictureInPictureDetails;
import com.android.settings.applications.PictureInPictureSettings;
import com.android.settings.applications.ProcessStatsSummary; import com.android.settings.applications.ProcessStatsSummary;
import com.android.settings.applications.ProcessStatsUi; import com.android.settings.applications.ProcessStatsUi;
import com.android.settings.applications.UsageAccessDetails; import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.VrListenerSettings; import com.android.settings.applications.VrListenerSettings;
import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.applications.AppInfoDashboardFragment; import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.applications.appinfo.DrawOverlayDetails;
import com.android.settings.applications.appinfo.ExternalSourcesDetails;
import com.android.settings.applications.appinfo.PictureInPictureDetails;
import com.android.settings.applications.appinfo.PictureInPictureSettings;
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.applications.assist.ManageAssist; import com.android.settings.applications.assist.ManageAssist;
import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment; import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;

View File

@@ -20,7 +20,7 @@ com.android.settings.datausage.AppDataUsage
com.android.settings.datausage.DataPlanUsageSummary com.android.settings.datausage.DataPlanUsageSummary
com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard
com.android.settings.applications.ManageDomainUrls com.android.settings.applications.ManageDomainUrls
com.android.settings.applications.WriteSettingsDetails com.android.settings.applications.appinfo.WriteSettingsDetails
com.android.settings.applications.ProcessStatsSummary com.android.settings.applications.ProcessStatsSummary
com.android.settings.users.RestrictedProfileSettings com.android.settings.users.RestrictedProfileSettings
com.android.settings.accounts.ChooseAccountActivity com.android.settings.accounts.ChooseAccountActivity
@@ -36,7 +36,7 @@ com.android.settings.accessibility.ToggleSelectToSpeakPreferenceFragmentForSetup
com.android.settings.accounts.AccountSyncSettings com.android.settings.accounts.AccountSyncSettings
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
com.android.settings.inputmethod.InputMethodAndSubtypeEnabler com.android.settings.inputmethod.InputMethodAndSubtypeEnabler
com.android.settings.applications.DrawOverlayDetails com.android.settings.applications.appinfo.DrawOverlayDetails
com.android.settings.backup.ToggleBackupSettingFragment com.android.settings.backup.ToggleBackupSettingFragment
com.android.settings.users.UserDetailsSettings com.android.settings.users.UserDetailsSettings
com.android.settings.datausage.UnrestrictedDataAccess com.android.settings.datausage.UnrestrictedDataAccess
@@ -59,9 +59,9 @@ com.android.settings.applications.AppStorageSettings
com.android.settings.notification.NotificationAccessSettings com.android.settings.notification.NotificationAccessSettings
com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment
com.android.settings.localepicker.LocaleListEditor com.android.settings.localepicker.LocaleListEditor
com.android.settings.applications.ExternalSourcesDetails com.android.settings.applications.appinfo.ExternalSourcesDetails
com.android.settings.applications.PictureInPictureSettings com.android.settings.applications.appinfo.PictureInPictureSettings
com.android.settings.applications.PictureInPictureDetails com.android.settings.applications.appinfo.PictureInPictureDetails
com.android.settings.ApnSettings com.android.settings.ApnSettings
com.android.settings.PrivacySettings com.android.settings.PrivacySettings
com.android.settings.WifiCallingSettings com.android.settings.WifiCallingSettings

View File

@@ -0,0 +1,120 @@
/*
* 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 android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.Manifest.permission.WRITE_SETTINGS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.TestConfig;
import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class DrawOverlayDetailPreferenceControllerTest {
@Mock
private UserManager mUserManager;
@Mock
private AppInfoDashboardFragment mFragment;
@Mock
private Preference mPreference;
private Context mContext;
private DrawOverlayDetailPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(new DrawOverlayDetailPreferenceController(mContext, mFragment));
final String key = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(key);
}
@Test
public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_noPermissionRequested_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
when(mFragment.getPackageInfo()).thenReturn(new PackageInfo());
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_noSystemAlertWindowPermission_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
final PackageInfo info = new PackageInfo();
info.requestedPermissions = new String[] {WRITE_SETTINGS};
when(mFragment.getPackageInfo()).thenReturn(info);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_hasSystemAlertWindowPermission_shouldReturnAvailable() {
when(mUserManager.isManagedProfile()).thenReturn(false);
final PackageInfo info = new PackageInfo();
info.requestedPermissions = new String[] {SYSTEM_ALERT_WINDOW};
when(mFragment.getPackageInfo()).thenReturn(info);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getDetailFragmentClass_shouldReturnDrawOverlayDetails() {
assertThat(mController.getDetailFragmentClass()).isEqualTo(DrawOverlayDetails.class);
}
@Test
public void updateState_shouldSetSummary() {
final String summary = "test summary";
doReturn(summary).when(mController).getSummary();
mController.updateState(mPreference);
verify(mPreference).setSummary(summary);
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License * limitations under the License
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.nullable; import static org.mockito.Matchers.nullable;

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.TestConfig;
import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ExternalSourceDetailPreferenceControllerTest {
@Mock
private UserManager mUserManager;
@Mock
private AppInfoDashboardFragment mFragment;
@Mock
private Preference mPreference;
private Context mContext;
private ExternalSourceDetailPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(
new ExternalSourceDetailPreferenceController(mContext, mFragment, "Package1"));
final String key = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(key);
}
@Test
public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_notPotentialAppSource_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
doReturn(false).when(mController).isPotentialAppSource();
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_isPotentialAppSource_shouldReturnAvailable() {
when(mUserManager.isManagedProfile()).thenReturn(false);
doReturn(true).when(mController).isPotentialAppSource();
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getDetailFragmentClass_shouldReturnExternalSourcesDetails() {
assertThat(mController.getDetailFragmentClass()).isEqualTo(ExternalSourcesDetails.class);
}
@Test
public void updateState_shouldSetSummary() {
final String summary = "test summary";
doReturn(summary).when(mController).getPreferenceSummary();
mController.updateState(mPreference);
verify(mPreference).setSummary(summary);
}
}

View File

@@ -0,0 +1,107 @@
/*
* 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.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class PictureInPictureDetailPreferenceControllerTest {
@Mock
private UserManager mUserManager;
@Mock
private AppInfoDashboardFragment mFragment;
@Mock
private Preference mPreference;
private Context mContext;
private PictureInPictureDetailPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(
new PictureInPictureDetailPreferenceController(mContext, mFragment, "Package1"));
final String key = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(key);
}
@Test
public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_noPictureInPictureActivities_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
doReturn(false).when(mController).hasPictureInPictureActivites();
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_hasPictureInPictureActivities_shouldReturnAvailable() {
when(mUserManager.isManagedProfile()).thenReturn(false);
doReturn(true).when(mController).hasPictureInPictureActivites();
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getDetailFragmentClass_shouldReturnPictureInPictureDetails() {
assertThat(mController.getDetailFragmentClass()).isEqualTo(PictureInPictureDetails.class);
}
@Test
public void updateState_shouldSetSummary() {
final int summary = R.string.app_permission_summary_allowed;
doReturn(summary).when(mController).getPreferenceSummary();
mController.updateState(mPreference);
verify(mPreference).setSummary(summary);
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License * limitations under the License
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;

View File

@@ -14,7 +14,7 @@
* limitations under the License * limitations under the License
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;

View File

@@ -14,7 +14,7 @@
* limitations under the License * limitations under the License
*/ */
package com.android.settings.applications; package com.android.settings.applications.appinfo;
import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.eq; import static org.mockito.Matchers.eq;

View File

@@ -0,0 +1,120 @@
/*
* 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 android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.Manifest.permission.WRITE_SETTINGS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import com.android.settings.TestConfig;
import com.android.settings.applications.AppInfoDashboardFragment;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WriteSystemSettingsPreferenceControllerTest {
@Mock
private UserManager mUserManager;
@Mock
private AppInfoDashboardFragment mFragment;
@Mock
private Preference mPreference;
private Context mContext;
private WriteSystemSettingsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
mController = spy(new WriteSystemSettingsPreferenceController(mContext, mFragment));
final String key = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(key);
}
@Test
public void getAvailabilityStatus_managedProfile_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_noPermissionRequested_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
when(mFragment.getPackageInfo()).thenReturn(new PackageInfo());
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_noWriteSettingsPermission_shouldReturnDisabled() {
when(mUserManager.isManagedProfile()).thenReturn(false);
final PackageInfo info = new PackageInfo();
info.requestedPermissions = new String[] {SYSTEM_ALERT_WINDOW};
when(mFragment.getPackageInfo()).thenReturn(info);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.DISABLED_FOR_USER);
}
@Test
public void getAvailabilityStatus_hasWriteSettingsPermission_shouldReturnAvailable() {
when(mUserManager.isManagedProfile()).thenReturn(false);
final PackageInfo info = new PackageInfo();
info.requestedPermissions = new String[] {WRITE_SETTINGS};
when(mFragment.getPackageInfo()).thenReturn(info);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getDetailFragmentClass_shouldReturnWriteSettingsDetails() {
assertThat(mController.getDetailFragmentClass()).isEqualTo(WriteSettingsDetails.class);
}
@Test
public void updateState_shouldSetSummary() {
final String summary = "test summary";
doReturn(summary).when(mController).getSummary();
mController.updateState(mPreference);
verify(mPreference).setSummary(summary);
}
}