/* * 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.zte.appopscontrol.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.PreferenceActivity; 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.zte.appopscontrol.R; import com.zte.appopscontrol.applications.AppOpsDetails; import com.zte.appopscontrol.applications.AppOpsState; import com.zte.appopscontrol.applications.AppOpsSummaryActivity; import com.zte.appopscontrol.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(); //zte test Fragment f = null;//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; //zte test //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); //PreferenceActivity pa = (PreferenceActivity)getActivity(); //pa.startPreferencePanel(AppOpsDetails.class.getName(), args, // R.string.app_ops_settings, null, this, 2); AppOpsDetails appDetailFragment = new AppOpsDetails(); appDetailFragment.setArguments(args); getFragmentManager().beginTransaction() .replace(R.id.fragment_container,appDetailFragment).commit(); 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; //zte test //app.privacyGuardEnabled = mAppOps.getPrivacyGuardSettingForPackage( // app.uid, app.packageName); app.privacyGuardEnabled = false; 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(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"); } 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.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); } } }