Added Warning dialog when enabling usage access for app
The user is now thoroughly warned about enabling third party app access to device history. Change-Id: If8d49a47cae76e06f19cba117d3ec60075966541
This commit is contained in:
@@ -4333,9 +4333,15 @@
|
|||||||
<string name="credentials_configure_lock_screen_hint">You need to set a lock screen PIN or password before you can use credential storage.</string>
|
<string name="credentials_configure_lock_screen_hint">You need to set a lock screen PIN or password before you can use credential storage.</string>
|
||||||
|
|
||||||
<!-- Title of Usage Access preference item [CHAR LIMIT=30] -->
|
<!-- Title of Usage Access preference item [CHAR LIMIT=30] -->
|
||||||
<string name="usage_access_title">Usage access</string>
|
<string name="usage_access_title">Apps with usage access</string>
|
||||||
<!-- Summary of Usage Access preference item [CHAR LIMIT=80] -->
|
<!-- Header of list of apps in Usage Access screen [CHAR LIMIT=30] -->
|
||||||
<string name="usage_access_summary">Apps that have access to your device\'s usage history.</string>
|
<string name="usage_access_app_list_header">Apps requesting access</string>
|
||||||
|
<!-- Body of Usage Access preference screen [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="usage_access_body">Only allow apps you trust to have access to usage data. Apps you allow will have access to your app usage history, such as the last time an app was used, or the total time you spent using an app.</string>
|
||||||
|
<!-- AlertDialog title for warning user when enabling usage access [CHAR LIMIT=30] -->
|
||||||
|
<string name="allow_usage_access_title">Allow access?</string>
|
||||||
|
<!-- AlertDialog message for warning user when enabling usage access [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="allow_usage_access_message">If you allow access, this app can view general info about your apps, such as how often you use them."</string>
|
||||||
|
|
||||||
<!-- Sound settings screen, setting check box label -->
|
<!-- Sound settings screen, setting check box label -->
|
||||||
<string name="emergency_tone_title">Emergency tone</string>
|
<string name="emergency_tone_title">Emergency tone</string>
|
||||||
|
@@ -117,7 +117,6 @@
|
|||||||
|
|
||||||
<Preference android:key="usage_access"
|
<Preference android:key="usage_access"
|
||||||
android:title="@string/usage_access_title"
|
android:title="@string/usage_access_title"
|
||||||
android:summary="@string/usage_access_summary"
|
|
||||||
android:fragment="com.android.settings.UsageAccessSettings"/>
|
android:fragment="com.android.settings.UsageAccessSettings"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
@@ -16,4 +16,16 @@
|
|||||||
|
|
||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:key="usage_access"
|
android:key="usage_access"
|
||||||
android:title="@string/usage_access_title" />
|
android:title="@string/usage_access_title">
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:key="apps"
|
||||||
|
android:title="@string/usage_access_app_list_header"
|
||||||
|
android:persistent="false" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:summary="@string/usage_access_body"
|
||||||
|
android:persistent="false"
|
||||||
|
android:selectable="false" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
|
@@ -20,8 +20,12 @@ import com.android.internal.content.PackageMonitor;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.app.ActivityThread;
|
import android.app.ActivityThread;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.content.pm.IPackageManager;
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -30,6 +34,7 @@ import android.os.Bundle;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
|
import android.preference.PreferenceCategory;
|
||||||
import android.preference.SwitchPreference;
|
import android.preference.SwitchPreference;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -176,7 +181,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
|
|
||||||
if (newEntries == null) {
|
if (newEntries == null) {
|
||||||
mPackageEntryMap.clear();
|
mPackageEntryMap.clear();
|
||||||
getPreferenceScreen().removeAll();
|
mAppsCategory.removeAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +192,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
final PackageEntry newPackageEntry = newEntries.get(oldPackageEntry.packageName);
|
final PackageEntry newPackageEntry = newEntries.get(oldPackageEntry.packageName);
|
||||||
if (newPackageEntry == null) {
|
if (newPackageEntry == null) {
|
||||||
// This package has been removed.
|
// This package has been removed.
|
||||||
getPreferenceScreen().removePreference(oldPackageEntry.preference);
|
mAppsCategory.removePreference(oldPackageEntry.preference);
|
||||||
} else {
|
} else {
|
||||||
// This package already exists in the preference hierarchy, so reuse that
|
// This package already exists in the preference hierarchy, so reuse that
|
||||||
// Preference.
|
// Preference.
|
||||||
@@ -203,7 +208,7 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
packageEntry.preference = new SwitchPreference(mContext);
|
packageEntry.preference = new SwitchPreference(mContext);
|
||||||
packageEntry.preference.setPersistent(false);
|
packageEntry.preference.setPersistent(false);
|
||||||
packageEntry.preference.setOnPreferenceChangeListener(UsageAccessSettings.this);
|
packageEntry.preference.setOnPreferenceChangeListener(UsageAccessSettings.this);
|
||||||
getPreferenceScreen().addPreference(packageEntry.preference);
|
mAppsCategory.addPreference(packageEntry.preference);
|
||||||
}
|
}
|
||||||
updatePreference(packageEntry);
|
updatePreference(packageEntry);
|
||||||
}
|
}
|
||||||
@@ -232,20 +237,22 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldIgnorePackage(String packageName) {
|
static boolean shouldIgnorePackage(String packageName) {
|
||||||
return packageName.equals("android") || packageName.equals("com.android.settings");
|
return packageName.equals("android") || packageName.equals("com.android.settings");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayMap<String, PackageEntry> mPackageEntryMap = new ArrayMap<>();
|
|
||||||
private AppOpsManager mAppOpsManager;
|
|
||||||
private AppsRequestingAccessFetcher mLastFetcherTask;
|
private AppsRequestingAccessFetcher mLastFetcherTask;
|
||||||
|
ArrayMap<String, PackageEntry> mPackageEntryMap = new ArrayMap<>();
|
||||||
|
AppOpsManager mAppOpsManager;
|
||||||
|
PreferenceCategory mAppsCategory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.usage_access_settings);
|
addPreferencesFromResource(R.xml.usage_access_settings);
|
||||||
getPreferenceScreen().setOrderingAsAdded(false);
|
mAppsCategory = (PreferenceCategory) getPreferenceScreen().findPreference("apps");
|
||||||
|
mAppsCategory.setOrderingAsAdded(false);
|
||||||
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
|
mAppOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,13 +309,27 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
|
|
||||||
// Check if we need to do any work.
|
// Check if we need to do any work.
|
||||||
if (pe.appOpMode != newMode) {
|
if (pe.appOpMode != newMode) {
|
||||||
mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS,
|
if (newMode != AppOpsManager.MODE_ALLOWED) {
|
||||||
pe.packageInfo.applicationInfo.uid, packageName, newMode);
|
// Turning off the setting has no warning.
|
||||||
pe.appOpMode = newMode;
|
setNewMode(pe, newMode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turning on the setting has a Warning.
|
||||||
|
getFragmentManager().beginTransaction()
|
||||||
|
.add(new WarningDialog(pe), "warning")
|
||||||
|
.commit();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setNewMode(PackageEntry pe, int newMode) {
|
||||||
|
mAppOpsManager.setMode(AppOpsManager.OP_GET_USAGE_STATS,
|
||||||
|
pe.packageInfo.applicationInfo.uid, pe.packageName, newMode);
|
||||||
|
pe.appOpMode = newMode;
|
||||||
|
}
|
||||||
|
|
||||||
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
|
||||||
@Override
|
@Override
|
||||||
public void onPackageAdded(String packageName, int uid) {
|
public void onPackageAdded(String packageName, int uid) {
|
||||||
@@ -320,4 +341,34 @@ public class UsageAccessSettings extends SettingsPreferenceFragment implements
|
|||||||
updateInterestedApps();
|
updateInterestedApps();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private class WarningDialog extends DialogFragment
|
||||||
|
implements DialogInterface.OnClickListener {
|
||||||
|
private final PackageEntry mEntry;
|
||||||
|
|
||||||
|
public WarningDialog(PackageEntry pe) {
|
||||||
|
mEntry = pe;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
return new AlertDialog.Builder(getActivity())
|
||||||
|
.setTitle(R.string.allow_usage_access_title)
|
||||||
|
.setMessage(R.string.allow_usage_access_message)
|
||||||
|
.setIconAttribute(android.R.attr.alertDialogIcon)
|
||||||
|
.setNegativeButton(R.string.cancel, this)
|
||||||
|
.setPositiveButton(R.string.allow, this)
|
||||||
|
.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
if (which == DialogInterface.BUTTON_POSITIVE) {
|
||||||
|
setNewMode(mEntry, AppOpsManager.MODE_ALLOWED);
|
||||||
|
mEntry.preference.setChecked(true);
|
||||||
|
} else {
|
||||||
|
dialog.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user