diff options
author | Sam Mortimer <sam@mortimer.me.uk> | 2014-11-14 23:15:15 -0800 |
---|---|---|
committer | Roman Birg <roman@cyngn.com> | 2015-11-03 12:21:35 -0800 |
commit | db521697716ce627bb9dd574de86e60b756ca2fa (patch) | |
tree | 2eb2f067129e8d059f66a1d9fa0b7d75f7993527 /src/com/android/settings/privacyguard | |
parent | 45b8df16fd9f45f5bb4f4ecb72dbd567e829dcbd (diff) | |
download | packages_apps_Settings-db521697716ce627bb9dd574de86e60b756ca2fa.zip packages_apps_Settings-db521697716ce627bb9dd574de86e60b756ca2fa.tar.gz packages_apps_Settings-db521697716ce627bb9dd574de86e60b756ca2fa.tar.bz2 |
[2/2] Settings: Privacy Guard
PS2: * add ic_privacy_guard*.png from frameworks/base
* rebase
PS3: * enable AppOpsSummaryActivity
* use SubSettings on longclick
PS4: * move privacyguard settings category to just
below security
PS5: * rebase
Pulled together mostly (if not all) from:
Author: Steve Kondik <shade@chemlab.org>
Date: Tue Feb 25 14:02:16 2014 +0100
settings: Relocate Privacy Guard icons to framework
* So we can use them in the permission dialog for MODE_ASK
Change-Id: Ia9bac7dff0bbe91ae48db5d4b0d8f46feb9fdf86
Author: DvTonder <david.vantonder@gmail.com>
Date: Thu Jan 16 19:01:23 2014 -0500
Settings: Fix up top level "Privacy" section
Change-Id: Id4dbda10a891c793bc6eb3c42807cc0e3f6092cc
Author: Danny Baumann <dannybaumann@web.de>
Date: Fri Nov 8 13:37:07 2013 +0100
Add back privacy guard manager.
Change-Id: Ic9fbbae137bb8425fe72a6cdb2f17117351b5709
Author: Chirayu Desai <cdesai@cyanogenmod.org>
Date: Sat Dec 28 18:51:46 2013 +0530
PrivacyGuard: Specify a default value in Settings.getInt method call
* While privacy guard is enabled by default, the default value specified
here is returned only when the setting is not defined or not an integer.
Change-Id: Iaedffcc76a23a310aa7915f6a42ccce83ba5d2a6
Author: Matt Mower <mowerm@gmail.com>
Date: Wed Feb 5 19:40:37 2014 -0600
PrivacyGuard: confirm permissions reset
The button to reset all application permissions to enabled looks
suspiciously like a refresh button. Prompt the user with a confirmation
dialog to make sure they know what they've pressed.
Change-Id: I0444c5bf8e9533feccf890055d34d3200609c6f6
Change-Id: I2e10cb4d395e2e7e5141d2fadada9e9b21cd7fbf
Diffstat (limited to 'src/com/android/settings/privacyguard')
3 files changed, 697 insertions, 0 deletions
diff --git a/src/com/android/settings/privacyguard/PrivacyGuardAppListAdapter.java b/src/com/android/settings/privacyguard/PrivacyGuardAppListAdapter.java new file mode 100644 index 0000000..49555a9 --- /dev/null +++ b/src/com/android/settings/privacyguard/PrivacyGuardAppListAdapter.java @@ -0,0 +1,185 @@ +/* + * 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.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.SectionIndexer; +import android.widget.TextView; + +import com.android.settings.R; +import com.android.settings.privacyguard.PrivacyGuardManager.AppInfo; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class PrivacyGuardAppListAdapter extends BaseAdapter implements SectionIndexer { + + private LayoutInflater mInflater; + private PackageManager mPm; + + private List<AppInfo> mApps; + private String[] mSections; + private int[] mPositions; + private ConcurrentHashMap<String, Drawable> mIcons; + private Drawable mDefaultImg; + + private Context mContext; + + //constructor + public PrivacyGuardAppListAdapter(Context context, List<AppInfo> apps, + List<String> sections, List<Integer> positions) { + mContext = context; + mInflater = LayoutInflater.from(mContext); + mPm = context.getPackageManager(); + + mApps = apps; + mSections = sections.toArray(new String[sections.size()]); + mPositions = new int[positions.size()]; + for (int i = 0; i < positions.size(); i++) { + mPositions[i] = positions.get(i); + } + + // 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; + } + + @Override + public int getPositionForSection(int section) { + if (section < 0 || section >= mSections.length) { + return -1; + } + + return mPositions[section]; + } + + @Override + public int getSectionForPosition(int position) { + if (position < 0 || position >= getCount()) { + return -1; + } + + int index = Arrays.binarySearch(mPositions, position); + + /* + * Consider this example: section positions are 0, 3, 5; the supplied + * position is 4. The section corresponding to position 4 starts at + * position 3, so the expected return value is 1. Binary search will not + * find 4 in the array and thus will return -insertPosition-1, i.e. -3. + * To get from that number to the expected value of 1 we need to negate + * and subtract 2. + */ + return index >= 0 ? index : -index - 2; + } + + @Override + public Object[] getSections() { + return mSections; + } + + /** + * 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/privacyguard/PrivacyGuardManager.java b/src/com/android/settings/privacyguard/PrivacyGuardManager.java new file mode 100644 index 0000000..9fb8c9d --- /dev/null +++ b/src/com/android/settings/privacyguard/PrivacyGuardManager.java @@ -0,0 +1,423 @@ +/* + * 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.privacyguard; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.AppOpsManager; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentManager; +import android.content.ActivityNotFoundException; +import android.content.Context; +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.pm.Signature; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.TextUtils; +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 com.android.settings.Settings.AppOpsSummaryActivity; +import com.android.settings.SubSettings; +import com.android.settings.applications.AppOpsDetails; +import com.android.settings.applications.AppOpsState; +import com.android.settings.applications.AppOpsState.OpsTemplate; + +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; + private AppOpsManager mAppOps; + + private int mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION; + private int mSavedFirstItemOffset; + + // keys for extras and icicles + private final static String LAST_LIST_POS = "last_list_pos"; + private final static String LAST_LIST_OFFSET = "last_list_offset"; + + // holder for package data passed into the adapter + public static final class AppInfo { + String title; + String packageName; + boolean enabled; + boolean privacyGuardEnabled; + int uid; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + mActivity = getActivity(); + mPm = mActivity.getPackageManager(); + mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE); + + return inflater.inflate(R.layout.privacy_guard_manager, container, false); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + FragmentManager fm = getFragmentManager(); + Fragment f = fm.findFragmentById(R.id.privacy_guard_prefs); + if (f != null && !fm.isDestroyed()) { + fm.beginTransaction().remove(f).commit(); + } + } + + @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(); + } + + if (savedInstanceState != null) { + mSavedFirstVisiblePosition = savedInstanceState.getInt(LAST_LIST_POS, + AdapterView.INVALID_POSITION); + mSavedFirstItemOffset = savedInstanceState.getInt(LAST_LIST_OFFSET, 0); + } else { + mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION; + mSavedFirstItemOffset = 0; + } + + // load apps and construct the list + loadApps(); + + setHasOptionsMenu(true); + } + + @Override + public void onViewStateRestored(Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putInt(LAST_LIST_POS, mSavedFirstVisiblePosition); + outState.putInt(LAST_LIST_OFFSET, mSavedFirstItemOffset); + } + + @Override + public void onPause() { + super.onPause(); + + // Remember where the list is scrolled to so we can restore the scroll position + // when we come back to this activity and *after* we complete querying for the + // conversations. + mSavedFirstVisiblePosition = mAppsList.getFirstVisiblePosition(); + View firstChild = mAppsList.getChildAt(0); + mSavedFirstItemOffset = (firstChild == null) ? 0 : firstChild.getTop(); + } + + @Override + public void onResume() { + super.onResume(); + + // rebuild the list; the user might have changed settings inbetween + loadApps(); + + if (mSavedFirstVisiblePosition != AdapterView.INVALID_POSITION) { + mAppsList.setSelectionFromTop(mSavedFirstVisiblePosition, mSavedFirstItemOffset); + mSavedFirstVisiblePosition = AdapterView.INVALID_POSITION; + } + } + + 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()) { + mNoUserAppsInstalled.setText(R.string.privacy_guard_no_user_apps); + mNoUserAppsInstalled.setVisibility(View.VISIBLE); + mAppsList.setVisibility(View.GONE); + mAppsList.setAdapter(null); + } else { + mNoUserAppsInstalled.setVisibility(View.GONE); + mAppsList.setVisibility(View.VISIBLE); + mAdapter = createAdapter(); + mAppsList.setAdapter(mAdapter); + mAppsList.setFastScrollEnabled(true); + } + } + + private PrivacyGuardAppListAdapter createAdapter() { + String lastSectionIndex = null; + ArrayList<String> sections = new ArrayList<String>(); + ArrayList<Integer> positions = new ArrayList<Integer>(); + int count = mApps.size(), offset = 0; + + for (int i = 0; i < count; i++) { + AppInfo app = mApps.get(i); + String sectionIndex; + + if (!app.enabled) { + sectionIndex = "--"; //XXX + } else if (app.title.isEmpty()) { + sectionIndex = ""; + } else { + sectionIndex = app.title.substring(0, 1).toUpperCase(); + } + if (lastSectionIndex == null) { + lastSectionIndex = sectionIndex; + } + + if (!TextUtils.equals(sectionIndex, lastSectionIndex)) { + sections.add(sectionIndex); + positions.add(offset); + lastSectionIndex = sectionIndex; + } + offset++; + } + + return new PrivacyGuardAppListAdapter(mActivity, mApps, sections, positions); + } + + private void resetPrivacyGuard() { + if (mApps == null || mApps.isEmpty()) { + return; + } + showResetDialog(); + } + + @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; + mAppOps.setPrivacyGuardSettingForPackage(app.uid, 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); + + Bundle args = new Bundle(); + args.putString(AppOpsDetails.ARG_PACKAGE_NAME, app.packageName); + + SubSettings ssa = (SubSettings) getActivity(); + ssa.startPreferencePanel(AppOpsDetails.class.getName(), args, + R.string.app_ops_settings, null, this, 2); + 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 | PackageManager.GET_SIGNATURES); + boolean showSystemApps = shouldShowSystemApps(); + Signature platformCert; + + try { + PackageInfo sysInfo = mPm.getPackageInfo("android", PackageManager.GET_SIGNATURES); + platformCert = sysInfo.signatures[0]; + } catch (PackageManager.NameNotFoundException e) { + platformCert = null; + } + + for (PackageInfo info : packages) { + final ApplicationInfo appInfo = info.applicationInfo; + + // hide apps signed with the platform certificate to avoid the user + // shooting himself in the foot + if (platformCert != null && info.signatures != null + && platformCert.equals(info.signatures[0])) { + continue; + } + + // skip all system apps if they shall not be included + if (!showSystemApps && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + continue; + } + + AppInfo app = new AppInfo(); + app.title = appInfo.loadLabel(mPm).toString(); + app.packageName = info.packageName; + app.enabled = appInfo.enabled; + app.uid = info.applicationInfo.uid; + app.privacyGuardEnabled = mAppOps.getPrivacyGuardSettingForPackage( + app.uid, app.packageName); + apps.add(app); + } + + // sort the apps by their enabled state, then by title + Collections.sort(apps, new Comparator<AppInfo>() { + @Override + public int compare(AppInfo lhs, AppInfo rhs) { + if (lhs.enabled != rhs.enabled) { + return lhs.enabled ? -1 : 1; + } + return lhs.title.compareToIgnoreCase(rhs.title); + } + }); + + return apps; + } + + private boolean shouldShowSystemApps() { + return mPreferences.getBoolean("show_system_apps", false); + } + + 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(R.string.dlg_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"); + } + + private class ResetDialogFragment extends DialogFragment { + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.privacy_guard_reset_title) + .setMessage(R.string.privacy_guard_reset_text) + .setPositiveButton(R.string.dlg_ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // turn off privacy guard for all apps shown in the current list + for (AppInfo app : mApps) { + app.privacyGuardEnabled = false; + } + mAppOps.resetAllModes(); + mAdapter.notifyDataSetChanged(); + } + }) + .setNegativeButton(R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // Do nothing + } + }) + .create(); + } + } + + private void showResetDialog() { + ResetDialogFragment dialog = new ResetDialogFragment(); + dialog.show(getFragmentManager(), "reset_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()); + } + + @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.show_system_apps: + final String prefName = "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; + case R.id.advanced: + Intent i = new Intent(Intent.ACTION_MAIN); + i.setClass(mActivity, AppOpsSummaryActivity.class); + mActivity.startActivity(i); + return true; + default: + return super.onContextItemSelected(item); + } + } +} diff --git a/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java b/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java new file mode 100644 index 0000000..0f45d98 --- /dev/null +++ b/src/com/android/settings/privacyguard/PrivacyGuardPrefs.java @@ -0,0 +1,89 @@ +/* + * 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.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.internal.logging.MetricsLogger; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; +import cyanogenmod.providers.CMSettings; + +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); + + mPrivacyGuardDefault.setChecked(Settings.Secure.getInt(getContentResolver(), + CMSettings.Secure.PRIVACY_GUARD_DEFAULT, 0) == 1); + } + + @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(), + CMSettings.Secure.PRIVACY_GUARD_DEFAULT, value ? 1 : 0); + return true; + } + return false; + } + + @Override + protected int getMetricsCategory() { + return MetricsLogger.DONT_TRACK_ME_BRO; + } +} |