Merge "Add controllers for default app shortcut preferences."

This commit is contained in:
TreeHugger Robot
2017-12-08 02:20:11 +00:00
committed by Android (Google) Code Review
28 changed files with 961 additions and 211 deletions

View File

@@ -18,7 +18,6 @@ package com.android.settings.applications;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.Manifest.permission;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -47,7 +46,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
@@ -58,7 +56,6 @@ import android.view.MenuItem;
import android.view.View;
import android.webkit.IWebViewUpdateService;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.DeviceAdminAdd;
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.DefaultPhoneShortcutPreferenceController;
import com.android.settings.applications.appinfo.DefaultSmsShortcutPreferenceController;
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.appinfo.DrawOverlayDetailPreferenceController;
import com.android.settings.applications.appinfo.ExternalSourceDetailPreferenceController;
import com.android.settings.applications.appinfo.PictureInPictureDetailPreferenceController;
import com.android.settings.applications.appinfo.WriteSystemSettingsPreferenceController;
import com.android.settings.applications.instantapps.InstantAppButtonsController;
import com.android.settings.applications.manageapplications.ManageApplications;
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.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
import com.android.settingslib.RestrictedLockUtils;
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.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -149,6 +145,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
public static final String ARG_PACKAGE_UID = "uid";
protected static final boolean localLOGV = false;
private static final String KEY_ADVANCED_APP_INFO_CATEGORY = "advanced_app_info";
private EnforcedAdmin mAppsControlDisallowedAdmin;
private boolean mAppsControlDisallowedBySystem;
@@ -358,11 +355,6 @@ public class AppInfoDashboardFragment extends DashboardFragment
if (!refreshUi()) {
setIntentAndFinish(true, true);
}
if (mFinishing) {
return;
}
updateDynamicPrefs();
}
@Override
@@ -404,6 +396,17 @@ public class AppInfoDashboardFragment extends DashboardFragment
controllers.add(new DefaultEmergencyShortcutPreferenceController(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;
}
@@ -415,6 +418,9 @@ public class AppInfoDashboardFragment extends DashboardFragment
}
public PackageInfo getPackageInfo() {
if (mAppEntry == null) {
retrieveAppEntry();
}
return mPackageInfo;
}
@@ -603,7 +609,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
return false;
}
protected boolean refreshUi() {
@VisibleForTesting
boolean refreshUi() {
retrieveAppEntry();
if (mAppEntry == null) {
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,
SettingsPreferenceFragment caller, AppEntry appEntry) {
// start new fragment to display extended information
@@ -871,100 +874,10 @@ public class AppInfoDashboardFragment extends DashboardFragment
if (UserManager.get(getContext()).isManagedProfile()) {
return;
}
final PreferenceScreen screen = 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);
addAppInstallerInfoPref(getPreferenceScreen());
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) {
String installerPackageName =
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() {
getActivity().finishActivity(SUB_INFO_FRAGMENT);
getActivity().finishAndRemoveTask();
@@ -1112,7 +992,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
return mPackageName;
}
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) {
Intent intent = (args == null) ?
getActivity().getIntent() : (Intent) args.getParcelable("intent");
@@ -1229,7 +1109,7 @@ public class AppInfoDashboardFragment extends DashboardFragment
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_APP_INFO_ACTION;
return MetricsEvent.DIALOG_APP_INFO_ACTION;
}
@Override

View File

@@ -90,7 +90,7 @@ public class AppStateInstallAppsBridge extends AppStateBaseBridge {
return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName);
}
InstallAppsState createInstallAppsStateFor(String packageName, int uid) {
public InstallAppsState createInstallAppsStateFor(String packageName, int uid) {
final InstallAppsState appState = new InstallAppsState();
appState.permissionRequested = hasRequestedAppOpPermission(
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.SettingsPreferenceFragment;
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.DefaultEmergencyPreferenceController;
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
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.appinfo;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
@@ -29,12 +31,13 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateOverlayBridge;
import com.android.settings.applications.AppStateOverlayBridge.OverlayState;
import com.android.settings.overlay.FeatureFactory;
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_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 int [] APP_OPS_OP_CODE = {
@@ -57,7 +59,6 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref;
private Preference mOverlayPrefs;
private Preference mOverlayDesc;
private Intent mSettingsIntent;
private OverlayState mOverlayState;
@@ -70,16 +71,9 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
// find preferences
addPreferencesFromResource(R.xml.app_ops_permissions_details);
addPreferencesFromResource(R.xml.draw_overlay_permissions_details);
mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH);
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
mSwitchPref.setOnPreferenceChangeListener(this);
@@ -116,7 +110,8 @@ public class DrawOverlayDetails extends AppInfoWithHeader implements OnPreferenc
try {
getActivity().startActivityAsUser(mSettingsIntent, new UserHandle(mUserId));
} 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;
@@ -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!
mSwitchPref.setEnabled(mOverlayState.permissionDeclared && mOverlayState.controlEnabled);
mOverlayPrefs.setEnabled(isAllowed);
getPreferenceScreen().removePreference(mOverlayPrefs);
ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
PackageManager.GET_META_DATA, mUserId);
if (resolveInfo == null) {
if (findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) {
getPreferenceScreen().removePreference(mOverlayPrefs);
}
}
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
* 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_OK;
@@ -30,6 +30,8 @@ import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
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.settingslib.RestrictedSwitchPreference;
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
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.appinfo;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
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.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.overlay.FeatureFactory;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -38,42 +37,31 @@ public class PictureInPictureDetails extends AppInfoWithHeader
implements OnPreferenceChangeListener {
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 SwitchPreference mSwitchPref;
private Preference mOverlayDesc;
private Intent mSettingsIntent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 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);
mOverlayDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC);
getPreferenceScreen().removePreference(findPreference(KEY_APP_OPS_SETTINGS_PREFS));
// 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);
mOverlayDesc.setSummary(R.string.picture_in_picture_app_detail_summary);
// install event listeners
mSwitchPref.setOnPreferenceChangeListener(this);
mSettingsIntent = new Intent(Intent.ACTION_MAIN)
.setAction(Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mSwitchPref) {
logSpecialPermissionChange((Boolean) newValue, mPackageName);
setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid, mPackageName,
(Boolean) newValue);
setEnterPipStateForPackage(getActivity(), mPackageInfo.applicationInfo.uid,
mPackageName, (Boolean) newValue);
return true;
}
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
* {@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,
packageName);
return enabled ? R.string.app_permission_summary_allowed

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.appinfo;
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.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.notification.EmptyTextSettings;
import com.android.settings.widget.AppPreference;
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
* picture-in-picture.
*/
static boolean checkPackageHasPictureInPictureActivities(String packageName,
public static boolean checkPackageHasPictureInPictureActivities(String packageName,
ActivityInfo[] activities) {
ActivityInfoWrapper[] wrappedActivities = null;
if (activities != null) {

View File

@@ -13,13 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications;
package com.android.settings.applications.appinfo;
import android.app.AlertDialog;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
@@ -31,7 +33,9 @@ import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.applications.AppInfoWithHeader;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateWriteSettingsBridge;
import com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettingsState;
import com.android.settings.overlay.FeatureFactory;
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_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 = "WriteSettingsDetails";
private static final int [] APP_OPS_OP_CODE = {
@@ -55,7 +58,6 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
private AppOpsManager mAppOpsManager;
private SwitchPreference mSwitchPref;
private Preference mWriteSettingsPrefs;
private Preference mWriteSettingsDesc;
private Intent mSettingsIntent;
private WriteSettingsState mWriteSettingsState;
@@ -67,15 +69,9 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
mAppBridge = new AppStateWriteSettingsBridge(context, mState, null);
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);
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);
mWriteSettingsPrefs.setOnPreferenceClickListener(this);
@@ -147,8 +143,13 @@ public class WriteSettingsDetails extends AppInfoWithHeader implements OnPrefere
// you can't ask a user for a permission you didn't even declare!
mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared);
mWriteSettingsPrefs.setEnabled(canWrite);
if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) {
getPreferenceScreen().removePreference(mWriteSettingsPrefs);
ResolveInfo resolveInfo = mPm.resolveActivityAsUser(mSettingsIntent,
PackageManager.GET_META_DATA, mUserId);
if (resolveInfo == null) {
if (getPreferenceScreen().findPreference(KEY_APP_OPS_SETTINGS_PREFS) != null) {
getPreferenceScreen().removePreference(mWriteSettingsPrefs);
}
}
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.AppStorageSettings;
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.InstalledAppDetails;
import com.android.settings.applications.NotificationApps;
import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.WriteSettingsDetails;
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.InstrumentedPreferenceFragment;
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.applications.AppAndNotificationDashboardFragment;
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.ManageDomainUrls;
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.ProcessStatsUi;
import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.VrListenerSettings;
import com.android.settings.applications.WriteSettingsDetails;
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.manageapplications.ManageApplications;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;