summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/settings/SecuritySettings.java13
-rw-r--r--src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardAppListAdapter.java140
-rw-r--r--src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardManager.java318
-rw-r--r--src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardPrefs.java86
4 files changed, 544 insertions, 13 deletions
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index b01dc74..b966bc7 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -94,7 +94,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String LOCKSCREEN_QUICK_UNLOCK_CONTROL = "quick_unlock_control";
private static final String KEY_VIBRATE_PREF = "lockscreen_vibrate";
private static final String KEY_SMS_SECURITY_CHECK_PREF = "sms_security_check_limit";
- private static final String KEY_PRIVACY_GUARD_DEFAULT = "privacy_guard_default";
private static final String KEY_APP_SECURITY_CATEGORY = "app_security";
DevicePolicyManager mDPM;
@@ -128,7 +127,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
private CheckBoxPreference mHomeUnlock;
private CheckBoxPreference mQuickUnlockScreen;
private ListPreference mSmsSecurityCheck;
- private CheckBoxPreference mPrivacyGuardDefault;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -410,14 +408,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
root.findPreference(KEY_APP_SECURITY_CATEGORY);
appCategory.removePreference(mSmsSecurityCheck);
}
-
- mPrivacyGuardDefault = (CheckBoxPreference) findPreference(KEY_PRIVACY_GUARD_DEFAULT);
- try {
- mPrivacyGuardDefault.setChecked(Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.PRIVACY_GUARD_DEFAULT) == 1);
- } catch (SettingNotFoundException e) {
- mPrivacyGuardDefault.setChecked(false);
- }
}
return root;
@@ -708,9 +698,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
} else if (KEY_TOGGLE_VERIFY_APPLICATIONS.equals(key)) {
Settings.Global.putInt(getContentResolver(), Settings.Global.PACKAGE_VERIFIER_ENABLE,
mToggleVerifyApps.isChecked() ? 1 : 0);
- } else if (KEY_PRIVACY_GUARD_DEFAULT.equals(key)) {
- Settings.Secure.putInt(getContentResolver(), Settings.Secure.PRIVACY_GUARD_DEFAULT,
- mPrivacyGuardDefault.isChecked() ? 1 : 0);
} else {
// If we didn't handle it, let preferences handle it.
return super.onPreferenceTreeClick(preferenceScreen, preference);
diff --git a/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardAppListAdapter.java b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardAppListAdapter.java
new file mode 100644
index 0000000..4c7e815
--- /dev/null
+++ b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardAppListAdapter.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2013 SlimRoms 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.cyanogenmod.privacyguard;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settings.cyanogenmod.privacyguard.PrivacyGuardManager.AppInfo;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class PrivacyGuardAppListAdapter extends BaseAdapter {
+
+ private LayoutInflater mInflater;
+ private PackageManager mPm;
+
+ private List<AppInfo> mApps;
+ private ConcurrentHashMap<String, Drawable> mIcons;
+ private Drawable mDefaultImg;
+
+ private Context mContext;
+
+ //constructor
+ public PrivacyGuardAppListAdapter(Context context, List<AppInfo> apps) {
+ mContext = context;
+ mInflater = LayoutInflater.from(mContext);
+ mPm = context.getPackageManager();
+ mApps = apps;
+
+ // set the default icon till the actual app icon is loaded in async task
+ mDefaultImg = mContext.getResources().getDrawable(android.R.mipmap.sym_def_app_icon);
+ mIcons = new ConcurrentHashMap<String, Drawable>();
+
+ new LoadIconsTask().execute(apps.toArray(new PrivacyGuardManager.AppInfo[]{}));
+ }
+
+ @Override
+ public int getCount() {
+ return mApps.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mApps.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ PrivacyGuardAppViewHolder appHolder;
+
+ if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.privacy_guard_manager_list_row, null);
+
+ // creates a ViewHolder and children references
+ appHolder = new PrivacyGuardAppViewHolder();
+ appHolder.title = (TextView) convertView.findViewById(R.id.app_title);
+ appHolder.icon = (ImageView) convertView.findViewById(R.id.app_icon);
+ appHolder.privacyGuardIcon = (ImageView) convertView.findViewById(R.id.app_privacy_guard_icon);
+ convertView.setTag(appHolder);
+ } else {
+ appHolder = (PrivacyGuardAppViewHolder) convertView.getTag();
+ }
+
+ PrivacyGuardManager.AppInfo app = mApps.get(position);
+
+ appHolder.title.setText(app.title);
+
+ Drawable icon = mIcons.get(app.packageName);
+ appHolder.icon.setImageDrawable(icon != null ? icon : mDefaultImg);
+
+ int privacyGuardDrawableResId = app.privacyGuardEnabled
+ ? R.drawable.ic_privacy_guard : R.drawable.ic_privacy_guard_off;
+ appHolder.privacyGuardIcon.setImageResource(privacyGuardDrawableResId);
+
+ return convertView;
+ }
+
+ /**
+ * An asynchronous task to load the icons of the installed applications.
+ */
+ private class LoadIconsTask extends AsyncTask<PrivacyGuardManager.AppInfo, Void, Void> {
+ @Override
+ protected Void doInBackground(PrivacyGuardManager.AppInfo... apps) {
+ for (PrivacyGuardManager.AppInfo app : apps) {
+ try {
+ Drawable icon = mPm.getApplicationIcon(app.packageName);
+ mIcons.put(app.packageName, icon);
+ publishProgress();
+ } catch (PackageManager.NameNotFoundException e) {
+ // ignored; app will show up with default image
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onProgressUpdate(Void... progress) {
+ notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * App view holder used to reuse the views inside the list.
+ */
+ public static class PrivacyGuardAppViewHolder {
+ TextView title;
+ ImageView icon;
+ ImageView privacyGuardIcon;
+ }
+}
diff --git a/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardManager.java b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardManager.java
new file mode 100644
index 0000000..efb05a4
--- /dev/null
+++ b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardManager.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 SlimRoms 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.cyanogenmod.privacyguard;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.ActivityNotFoundException;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class PrivacyGuardManager extends Fragment
+ implements OnItemClickListener, OnItemLongClickListener {
+
+ private static final String TAG = "PrivacyGuardManager";
+
+ private TextView mNoUserAppsInstalled;
+ private ListView mAppsList;
+ private PrivacyGuardAppListAdapter mAdapter;
+ private List<AppInfo> mApps;
+
+ private PackageManager mPm;
+ private Activity mActivity;
+
+ private SharedPreferences mPreferences;
+
+ // array of critical permissions where privacy guard
+ // can hide the information
+ private static final String[] PERMISSION_FILTER = new String[] {
+ android.Manifest.permission.ACCESS_COARSE_LOCATION,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS,
+ android.Manifest.permission.READ_HISTORY_BOOKMARKS,
+ android.Manifest.permission.WRITE_HISTORY_BOOKMARKS,
+ android.Manifest.permission.READ_CALENDAR,
+ android.Manifest.permission.WRITE_CALENDAR,
+ android.Manifest.permission.READ_CONTACTS,
+ android.Manifest.permission.WRITE_CONTACTS,
+ android.Manifest.permission.READ_CALL_LOG,
+ android.Manifest.permission.WRITE_CALL_LOG,
+ "com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL",
+ android.Manifest.permission.READ_SMS,
+ android.Manifest.permission.RECEIVE_SMS,
+ android.Manifest.permission.SEND_SMS,
+ android.Manifest.permission.WRITE_SMS,
+ android.Manifest.permission.BROADCAST_SMS
+ };
+
+ // holder for package data passed into the adapter
+ public static final class AppInfo {
+ String title;
+ String packageName;
+ boolean privacyGuardEnabled;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+
+ mActivity = getActivity();
+ mPm = mActivity.getPackageManager();
+
+ return inflater.inflate(R.layout.privacy_guard_manager, container, false);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ mNoUserAppsInstalled = (TextView) mActivity.findViewById(R.id.error);
+
+ mAppsList = (ListView) mActivity.findViewById(R.id.apps_list);
+ mAppsList.setOnItemClickListener(this);
+ mAppsList.setOnItemLongClickListener(this);
+
+ // get shared preference
+ mPreferences = mActivity.getSharedPreferences("privacy_guard_manager", Activity.MODE_PRIVATE);
+ if (!mPreferences.getBoolean("first_help_shown", false)) {
+ showHelp();
+ }
+
+ // load apps and construct the list
+ loadApps();
+ setHasOptionsMenu(true);
+ }
+
+ private void loadApps() {
+ mApps = loadInstalledApps();
+
+ // if app list is empty inform the user
+ // else go ahead and construct the list
+ if (mApps == null || mApps.isEmpty()) {
+ if (shouldFilterByPermission()) {
+ mNoUserAppsInstalled.setText(R.string.privacy_guard_filter_does_not_match);
+ } else {
+ mNoUserAppsInstalled.setText(R.string.privacy_guard_no_user_apps);
+ }
+ mNoUserAppsInstalled.setVisibility(View.VISIBLE);
+ mAppsList.setVisibility(View.GONE);
+ } else {
+ mNoUserAppsInstalled.setVisibility(View.GONE);
+ mAppsList.setVisibility(View.VISIBLE);
+ mAdapter = new PrivacyGuardAppListAdapter(mActivity, mApps);
+ mAppsList.setAdapter(mAdapter);
+ }
+ }
+
+ private void resetPrivacyGuard() {
+ if (mApps == null || mApps.isEmpty()) {
+ return;
+ }
+ // turn off privacy guard for all apps shown in the current list
+ for (AppInfo app : mApps) {
+ if (app.privacyGuardEnabled) {
+ mPm.setPrivacyGuardSetting(app.packageName, false);
+ app.privacyGuardEnabled = false;
+ }
+ }
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ // on click change the privacy guard status for this item
+ final AppInfo app = (AppInfo) parent.getItemAtPosition(position);
+
+ app.privacyGuardEnabled = !app.privacyGuardEnabled;
+ mPm.setPrivacyGuardSetting(app.packageName, app.privacyGuardEnabled);
+
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
+ // on long click open app details window
+ final AppInfo app = (AppInfo) parent.getItemAtPosition(position);
+
+ try {
+ startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+ Uri.parse("package:" + app.packageName)));
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Couldn't open app details activity", e);
+ }
+
+ return true;
+ }
+
+ /**
+ * Uses the package manager to query for all currently installed apps
+ * for the list.
+ *
+ * @return the complete List off installed applications (@code PrivacyGuardAppInfo)
+ */
+ private List<AppInfo> loadInstalledApps() {
+ List<AppInfo> apps = new ArrayList<AppInfo>();
+ List<PackageInfo> packages = mPm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
+ boolean showSystemApps = shouldShowSystemApps();
+ boolean filterByPermission = shouldFilterByPermission();
+
+ for (PackageInfo info : packages) {
+ final ApplicationInfo appInfo = info.applicationInfo;
+
+ // skip system apps if they shall not be included
+ if (!showSystemApps && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ continue;
+ }
+
+ if (filterByPermission) {
+ final String[] requestedPermissions = info.requestedPermissions;
+ if (requestedPermissions == null || !filterAppPermissions(requestedPermissions)) {
+ continue;
+ }
+ }
+
+ AppInfo app = new AppInfo();
+ app.title = appInfo.loadLabel(mPm).toString();
+ app.packageName = info.packageName;
+ app.privacyGuardEnabled = mPm.getPrivacyGuardSetting(app.packageName);
+ apps.add(app);
+ }
+
+ // sort the apps by title
+ Collections.sort(apps, new Comparator<AppInfo>() {
+ @Override
+ public int compare(AppInfo lhs, AppInfo rhs) {
+ return lhs.title.compareToIgnoreCase(rhs.title);
+ }
+ });
+
+ return apps;
+ }
+
+ private boolean filterAppPermissions(final String[] requestedPermissions) {
+ for (String requested : requestedPermissions) {
+ for (String filtered : PERMISSION_FILTER) {
+ if (requested.equals(filtered)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean shouldShowSystemApps() {
+ return mPreferences.getBoolean("show_system_apps", false);
+ }
+
+ private boolean shouldFilterByPermission() {
+ return mPreferences.getBoolean("filter_by_permission", true);
+ }
+
+ private class HelpDialogFragment extends DialogFragment {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.privacy_guard_help_title)
+ .setMessage(R.string.privacy_guard_help_text)
+ .setNegativeButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.cancel();
+ }
+ })
+ .create();
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ mPreferences.edit().putBoolean("first_help_shown", true).commit();
+ }
+ }
+
+ private void showHelp() {
+ HelpDialogFragment fragment = new HelpDialogFragment();
+ fragment.show(getFragmentManager(), "help_dialog");
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.privacy_guard_manager, menu);
+ menu.findItem(R.id.show_system_apps).setChecked(shouldShowSystemApps());
+ menu.findItem(R.id.filter_app_permissions).setChecked(shouldFilterByPermission());
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.help:
+ showHelp();
+ return true;
+ case R.id.reset:
+ resetPrivacyGuard();
+ return true;
+ case R.id.filter_app_permissions:
+ case R.id.show_system_apps:
+ final String prefName = item.getItemId() == R.id.filter_app_permissions
+ ? "filter_by_permission" : "show_system_apps";
+ // set the menu checkbox and save it in
+ // shared preference and rebuild the list
+ item.setChecked(!item.isChecked());
+ mPreferences.edit().putBoolean(prefName, item.isChecked()).commit();
+ loadApps();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // rebuild the list; the user might have changed settings inbetween
+ loadApps();
+ }
+}
diff --git a/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardPrefs.java b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardPrefs.java
new file mode 100644
index 0000000..6d18952
--- /dev/null
+++ b/src/com/android/settings/cyanogenmod/privacyguard/PrivacyGuardPrefs.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Slimroms
+ *
+ * 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.cyanogenmod.privacyguard;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ListView;
+
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+
+public class PrivacyGuardPrefs extends SettingsPreferenceFragment implements
+ OnPreferenceChangeListener {
+
+ private static final String TAG = "PrivacyGuardPrefs";
+
+ private static final String KEY_PRIVACY_GUARD_DEFAULT = "privacy_guard_default";
+
+ private CheckBoxPreference mPrivacyGuardDefault;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ addPreferencesFromResource(R.xml.privacy_guard_prefs);
+ PreferenceScreen prefSet = getPreferenceScreen();
+
+ mPrivacyGuardDefault = (CheckBoxPreference) findPreference(KEY_PRIVACY_GUARD_DEFAULT);
+ mPrivacyGuardDefault.setOnPreferenceChangeListener(this);
+
+ try {
+ mPrivacyGuardDefault.setChecked(Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.PRIVACY_GUARD_DEFAULT) == 1);
+ } catch (SettingNotFoundException e) {
+ mPrivacyGuardDefault.setChecked(false);
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater,
+ ViewGroup container, Bundle savedInstanceState) {
+ final View view = super.onCreateView(inflater, container, savedInstanceState);
+ final ListView list = (ListView) view.findViewById(android.R.id.list);
+ // our container already takes care of the padding
+ int paddingTop = list.getPaddingTop();
+ int paddingBottom = list.getPaddingBottom();
+ list.setPadding(0, paddingTop, 0, paddingBottom);
+ return view;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mPrivacyGuardDefault) {
+ boolean value = (Boolean) newValue;
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.PRIVACY_GUARD_DEFAULT, value ? 1 : 0);
+ return true;
+ }
+ return false;
+ }
+}