com.koushikdutta.superuser.FragmentMain.java Source code

Java tutorial

Introduction

Here is the source code for com.koushikdutta.superuser.FragmentMain.java

Source

/**
 * Superuser
 * Copyright (C) 2016 Pierre-Hugues Husson (phhusson)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **/

package com.koushikdutta.superuser;

import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.util.Pair;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.kabouzeid.appthemehelper.util.ATHUtil;
import com.koushikdutta.superuser.db.SuDatabaseHelper;
import com.koushikdutta.superuser.db.UidPolicy;
import com.koushikdutta.superuser.helper.Settings;
import com.koushikdutta.superuser.helper.Theme;
import com.koushikdutta.superuser.helper.recycler.GridDividerItemDecoration;
import com.koushikdutta.superuser.helper.recycler.GridTopOffsetItemDecoration;
import com.koushikdutta.superuser.helper.recycler.StartOffsetItemDecoration;
import com.koushikdutta.superuser.util.Util;
import com.koushikdutta.superuser.view.PinView;
import com.koushikdutta.superuser.view.RecyclerViewSwipeable;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.koushikdutta.superuser.MainActivity.data;
import static com.koushikdutta.superuser.MainActivity.logCount;

public class FragmentMain extends Fragment {

    public interface MainCallback {
        void onListChanged(int which);

        void onGridSpanChanged(int which, int val);
    }

    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            //load(); This creates an unpleasant flicker. Better to change a single item

            if (intent == null || intent.getExtras() == null || adapter == null)
                return;

            String pkg = intent.getStringExtra("pkg");

            int pos = adapter.getPositionByPackage(pkg);

            if (pos == -1)
                return;

            String log = logCount.get(pkg);

            if (log == null) {
                if (intent.getStringExtra("policy").equals(UidPolicy.ALLOW))
                    log = "1+0";

                else if (intent.getStringExtra("policy").equals(UidPolicy.DENY))
                    log = "0+1";

                logCount.put(pkg, log);

                ListItem item = adapter.getVisible().get(pos);

                int i = data.indexOf(item);

                item.setItem3(getString(R.string.today));

                data.set(i, item);

            } else {
                if (intent.getStringExtra("policy").equals(UidPolicy.ALLOW))
                    log = log.replace(log.substring(0, log.indexOf("+")),
                            String.valueOf(Integer.parseInt(log.split("\\+")[0]) + 1));

                else if (intent.getStringExtra("policy").equals(UidPolicy.DENY))
                    log = log.replace(log.substring(log.indexOf("+") + 1),
                            String.valueOf(Integer.parseInt(log.split("\\+")[1]) + 1));

                for (Map.Entry<String, String> entry : logCount.entrySet()) {
                    if (entry.getKey().equals(pkg))
                        entry.setValue(log);
                }
            }

            adapter.notifyItemChanged(pos);
        }
    };

    public static final int FRAGMENT_ALLOWED = 0;
    public static final int FRAGMENT_DENIED = 1;
    private static final String DATA_BUNDLE_KEY = "deleted";

    private CoordinatorLayout coordinatorLayout;

    //TabLayout tabLayout;

    //private ViewPager viewPager;

    private TextView empty;
    private RecyclerViewSwipeable recycler;

    private Context context;
    private SharedPreferences pref;

    private MainCallback callback;

    private RecyclerViewSwipeable.LayoutManagerSwipeable layoutManager;
    private AppAdapter adapter;

    static boolean SHOULD_RELOAD = false;
    private boolean gridMode;

    private int type = FRAGMENT_ALLOWED;

    private String policy;

    public static FragmentMain newInstance(int which) {

        FragmentMain fragment = new FragmentMain();

        Bundle bundle = new Bundle();

        bundle.putInt("which", which);

        fragment.setArguments(bundle);

        return fragment;
    }

    public FragmentMain() {
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
            @Nullable Bundle savedInstanceState) {

        Bundle bundle = getArguments();
        type = bundle.getInt("which");

        switch (type) {
        case FRAGMENT_ALLOWED:
            policy = UidPolicy.ALLOW;
            break;

        case FRAGMENT_DENIED:
            policy = UidPolicy.DENY;
            break;
        }

        setHasOptionsMenu(true);

        View view = inflater.inflate(R.layout.fragment_main, container, false);

        empty = (TextView) view.findViewById(R.id.empty);
        if (policy.equalsIgnoreCase(UidPolicy.ALLOW))
            empty.setText(R.string.empty_allowed);
        else
            empty.setText(R.string.empty_denied);

        recycler = (RecyclerViewSwipeable) view.findViewById(R.id.recycler);

        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        context = getActivity();

        pref = PreferenceManager.getDefaultSharedPreferences(context);

        callback = (MainCallback) getActivity();

        LocalBroadcastManager.getInstance(context).registerReceiver(receiver,
                new IntentFilter(Common.INTENT_FILTER_MAIN));

        gridMode = pref.getBoolean("grid_mode", true);

        coordinatorLayout = (CoordinatorLayout) getActivity().findViewById(R.id.main_content);

        //tabLayout = (TabLayout) getActivity().findViewById(R.id.tabs);

        //viewPager = (ViewPager) getActivity().findViewById(R.id.container);

        int span = 0;

        if (gridMode) {
            layoutManager = new RecyclerViewSwipeable.LayoutManagerSwipeable(context, 1);

            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                span = pref.getInt("grid_size_port", 3);
                layoutManager.setSpanCount(span);

            } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                span = pref.getInt("grid_size_land", 4);
                layoutManager.setSpanCount(span);
            }

            Drawable divider = ContextCompat.getDrawable(context, R.drawable.divider_grid);
            divider.setColorFilter(new PorterDuffColorFilter(ATHUtil.resolveColor(context, R.attr.dividerGrid),
                    PorterDuff.Mode.SRC_ATOP));

            recycler.setLayoutManager(layoutManager);

            recycler.setLayoutAnimation(AnimationUtils.loadLayoutAnimation(context, R.anim.grid_layout_animation));

            recycler.addItemDecoration(new GridDividerItemDecoration(divider, divider, span));

            recycler.addItemDecoration(new GridTopOffsetItemDecoration(Util.toPx(context, 5), span));

        } else {
            recycler.setLayoutManager(new LinearLayoutManager(context));

            recycler.addItemDecoration(new StartOffsetItemDecoration(Util.toPx(context, 10)));
        }

        //recycler.setListener(clickListener);
        //recycler.setViewPager(viewPager);
        //recycler.setFragment(this);

        setData();
    }

    /*public Date getLastDate(int last) {
    return new Date((long) last * 1000);
    }*/

    public void setData() {
        if (adapter == null) {
            adapter = new AppAdapter(context);
            recycler.setAdapter(adapter);
        }

        adapter.filter();

        setEmpty();
    }

    private void setEmpty() {
        if (adapter.getVisible().isEmpty())
            empty.setVisibility(View.VISIBLE);
        else
            empty.setVisibility(View.GONE);
    }

    public void setSpan(int val) {
        layoutManager.setSpanCount(val);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);

        MenuItem mode = menu.add(Menu.NONE, Menu.NONE, 100, R.string.list_mode);
        mode.setTitle(pref.getBoolean("grid_mode", true) ? R.string.list_mode : R.string.grid_mode);
        mode.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

        mode.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {

                if (pref.edit().putBoolean("grid_mode", !pref.getBoolean("grid_mode", true)).commit())
                    getActivity().recreate();
                return true;
            }
        });

        if (!gridMode)
            return;

        MenuItem gridSize = menu.add(Menu.NONE, Menu.NONE, 101, R.string.grid_size);
        gridSize.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);

        gridSize.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {

                int sizePort = pref.getInt("grid_size_port", 3);
                int sizeLand = pref.getInt("grid_size_land", 4);

                final AlertDialog.Builder builder = new AlertDialog.Builder(context);

                View parent = LayoutInflater.from(context).inflate(R.layout.dialog_settings_grid_size, null);

                final AppCompatSeekBar seekPort = (AppCompatSeekBar) parent.findViewById(R.id.seek_port);
                seekPort.setProgress(sizePort - 3);

                final AppCompatSeekBar seekLand = (AppCompatSeekBar) parent.findViewById(R.id.seek_land);
                seekLand.setProgress(sizeLand - 3);

                builder.setView(parent);
                builder.setPositiveButton("?", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        SharedPreferences.Editor editor = pref.edit();

                        editor.putInt("grid_size_port", seekPort.getProgress() + 3);
                        editor.putInt("grid_size_land", seekLand.getProgress() + 3).apply();

                        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                            int val = seekPort.getProgress() + 3;
                            layoutManager.setSpanCount(val);
                            callback.onGridSpanChanged(type, val);

                        } else if (getResources()
                                .getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                            int val = seekLand.getProgress() + 3;
                            layoutManager.setSpanCount(val);
                            callback.onGridSpanChanged(type, val);
                        }
                    }
                });

                builder.show();
                return true;
            }
        });
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        callback = null;

        LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
    }

    private class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {

        class ViewHolder extends RecyclerView.ViewHolder {

            LinearLayout parent, overlayParent, titleParent;
            RelativeLayout iconParent;

            ImageView icon, left, right, menu;
            TextView title, subtitle, counter, counterIndicator;

            ViewHolder(View itemView) {
                super(itemView);

                parent = (LinearLayout) itemView.findViewById(R.id.parent);
                iconParent = (RelativeLayout) itemView.findViewById(R.id.icon_parent);
                overlayParent = (LinearLayout) itemView.findViewById(R.id.overlay_parent);
                titleParent = (LinearLayout) itemView.findViewById(R.id.title_parent);

                icon = (ImageView) itemView.findViewById(R.id.icon);
                left = (ImageView) itemView.findViewById(R.id.permission_left);
                right = (ImageView) itemView.findViewById(R.id.permission_right);
                menu = (ImageView) itemView.findViewById(R.id.menu);

                title = (TextView) itemView.findViewById(R.id.title);
                subtitle = (TextView) itemView.findViewById(R.id.subtitle);

                counter = (TextView) itemView.findViewById(R.id.counter);
                counterIndicator = (TextView) itemView.findViewById(R.id.counter_indicator);
            }
        }

        Context context;

        List<ListItem> visible;

        int counterBack, counterText;

        AppAdapter(Context context) {
            this.context = context;

            this.visible = new ArrayList<>();
            //filter();

            int defBack = 0xff555555;

            switch (((MainActivity) getActivity()).theme) {
            case MainActivity.PREF_LIGHT_THEME:
                defBack = 0xff656565;
            }

            counterBack = Theme.getCounterBackColor(pref, defBack);
            counterText = Theme.getCounterTextColor(pref);
        }

        List<ListItem> getVisible() {
            return visible;
        }

        @Override
        public int getItemCount() {
            return visible.size();
        }

        int getPositionByPackage(String pkg) {
            for (ListItem item : visible) {
                if (item.getPolicy().packageName.equals(pkg))
                    return visible.indexOf(item);
            }

            return -1;
        }

        void remove(int pos) {
            visible.remove(pos);
            notifyItemRemoved(pos);
        }

        /*void setPolicy(String policy) {
        filter(policy);
        }*/

        private void filter() {
            int size = visible.size();

            if (size > 0) {
                /*for (int i = 0; i < size; i++) Not needed anymore
                visible.remove(0);*/

                visible.clear();

                notifyItemRangeRemoved(0, size);
            }

            for (ListItem item : data) {
                if (item.getItem1().equals(policy))
                    visible.add(item);
            }

            notifyItemRangeInserted(0, visible.size());
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            return new ViewHolder(LayoutInflater.from(context)
                    .inflate(gridMode ? R.layout.grid_item : R.layout.list_item, parent, false));
        }

        @Override
        public void onBindViewHolder(final ViewHolder holder, int position) {

            final ListItem item = visible.get(position);

            holder.icon.setImageDrawable(item.getIcon());

            holder.title.setText(item.getItem2());

            if (!pref.getBoolean("ellipsize", false))
                holder.title.setMaxLines(2);

            holder.title.post(new Runnable() {
                @Override
                public void run() {
                    if (holder.title.getLineCount() > 1) {
                        holder.titleParent.setPadding(Util.toPx(context, 10), Util.toPx(context, 2),
                                Util.toPx(context, 10), Util.toPx(context, 3));

                    } else {
                        holder.titleParent.setPadding(Util.toPx(context, 10), Util.toPx(context, 10),
                                Util.toPx(context, 10), Util.toPx(context, 10));
                    }
                }
            });

            String count = logCount.get(item.getPolicy().packageName);

            if (count != null) {
                if (policy.equalsIgnoreCase(UidPolicy.ALLOW)) {
                    count = count.split("\\+")[0];
                    if (!gridMode)
                        holder.counterIndicator.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));

                } else {
                    count = count.split("\\+")[1];
                    if (!gridMode)
                        holder.counterIndicator.setTextColor(0xffc62828);
                }

                if (count.length() == 1)
                    count = "0" + count;
                holder.counter.setText(count);
            }

            if (item.getItem3() != null && Integer.parseInt(count) > 0) {
                holder.subtitle.setVisibility(View.VISIBLE);
                holder.counter.setVisibility(View.VISIBLE);
                if (!gridMode)
                    holder.counterIndicator.setVisibility(View.VISIBLE);

                holder.subtitle.setText(item.getItem3());

            } else {
                holder.subtitle.setVisibility(View.GONE);
                holder.counter.setVisibility(View.GONE);
                if (!gridMode)
                    holder.counterIndicator.setVisibility(View.GONE);
            }

            if (gridMode)
                handleGridItem(holder, item);
            else
                handleListItem(holder, item);
        }

        private void handleGridItem(final ViewHolder holder, final ListItem item) {

            holder.overlayParent.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    return true;
                }
            });

            setClickListener(holder.icon, holder.icon, item);

            holder.icon.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    Intent intent = getActivity().getPackageManager()
                            .getLaunchIntentForPackage(item.getPolicy().packageName);
                    if (intent != null)
                        startActivity(intent);
                    return false;
                }
            });

            holder.counter.setTextColor(counterText);

            GradientDrawable counterBackDrawable = (GradientDrawable) ContextCompat.getDrawable(context,
                    R.drawable.counter_back);
            counterBackDrawable.setColor(counterBack);

            holder.counter.setBackground(counterBackDrawable);

            holder.titleParent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (holder.overlayParent.getVisibility() == View.GONE)
                        showOverlay(holder);

                    else
                        hideOverlay(holder);
                }
            });

            if (policy.equalsIgnoreCase(UidPolicy.ALLOW)) {
                holder.left.setImageResource(R.drawable.ic_deny);
                holder.left.setColorFilter(0xfff44336);

            } else {
                holder.left.setImageResource(R.drawable.ic_allow);
                holder.left.setColorFilter(0xff4caf50);
            }

            holder.left.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    hideOverlay(holder);

                    if (Settings.isPinProtected(context))
                        handlePin(0, holder, item);
                    else
                        showSnack(0, holder, item);
                }
            });

            holder.right.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    hideOverlay(holder);

                    if (Settings.isPinProtected(context))
                        handlePin(1, holder, item);
                    else
                        showSnack(1, holder, item);
                }
            });
        }

        private void showOverlay(final ViewHolder holder) {
            final Animation up = AnimationUtils.loadAnimation(context, R.anim.abc_slide_in_bottom);
            final Animation down = AnimationUtils.loadAnimation(context, R.anim.abc_slide_out_bottom);

            down.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    holder.iconParent.setVisibility(View.GONE);
                    holder.overlayParent.startAnimation(up);
                    holder.overlayParent.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });

            holder.iconParent.startAnimation(down);

        }

        private void hideOverlay(final ViewHolder holder) {
            final Animation up = AnimationUtils.loadAnimation(context, R.anim.abc_slide_in_bottom);
            final Animation down = AnimationUtils.loadAnimation(context, R.anim.abc_slide_out_bottom);

            down.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }

                @Override
                public void onAnimationEnd(Animation animation) {
                    holder.overlayParent.setVisibility(View.GONE);
                    holder.iconParent.startAnimation(up);
                    holder.iconParent.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationRepeat(Animation animation) {
                }
            });

            holder.overlayParent.startAnimation(down);
        }

        private void handleListItem(final ViewHolder holder, final ListItem item) {

            setClickListener(holder.titleParent, holder.icon, item);

            holder.icon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    holder.icon.getHandler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            Intent intent = getActivity().getPackageManager()
                                    .getLaunchIntentForPackage(item.getPolicy().packageName);
                            if (intent != null)
                                startActivity(intent);
                        }
                    }, 200);
                }
            });

            holder.menu.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    PopupMenu popupMenu = new PopupMenu(context, holder.menu);

                    Menu menu = popupMenu.getMenu();

                    if (policy.equalsIgnoreCase(UidPolicy.ALLOW)) {
                        setMenu(0, menu.add(getString(R.string.deny)), holder, item);

                    } else {
                        setMenu(0, menu.add(getString(R.string.allow)), holder, item);
                    }

                    setMenu(1, menu.add(getString(R.string.revoke)), holder, item);

                    popupMenu.show();
                }
            });
        }

        private void setMenu(final int which, MenuItem menuItem, final ViewHolder holder, final ListItem item) {

            menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) {

                    switch (which) {
                    case 0:
                        if (Settings.isPinProtected(context))
                            handlePin(0, holder, item);
                        else
                            showSnack(0, holder, item);
                        break;

                    case 1:
                        if (Settings.isPinProtected(context))
                            handlePin(1, holder, item);
                        else
                            showSnack(1, holder, item);

                        break;
                    }

                    return false;
                }
            });
        }

        private void handlePin(final int which, final ViewHolder holder, final ListItem item) {
            final Dialog d = new Dialog(getContext());

            d.setContentView(
                    new PinView((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE),
                            R.layout.view_pin, null, null) {
                        public void onEnter(String password) {
                            super.onEnter(password);

                            if (Settings.checkPin(getActivity(), password)) {
                                d.dismiss();
                                handleRequest(which, holder, item);
                                return;
                            }

                            Toast.makeText(getActivity(), getString(R.string.incorrect_pin), Toast.LENGTH_SHORT)
                                    .show();
                        }

                        public void onCancel() {
                            super.onCancel();
                            d.dismiss();
                        }

                    }.getView(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT));

            d.show();
        }

        private void showSnack(final int which, final ViewHolder holder, final ListItem item) {
            Snackbar.make(coordinatorLayout, R.string.confirmation, Snackbar.LENGTH_INDEFINITE)
                    .setAction(R.string.yes, new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            handleRequest(which, holder, item);
                        }

                    }).show();

        }

        private void handleRequest(int which, ViewHolder holder, ListItem item) {
            final UidPolicy up = item.getPolicy();

            switch (which) {
            case 0:
                changePolicy(holder, up, item);
                break;
            case 1:
                revoke(holder, up, item);
                break;
            }
        }

        private void changePolicy(ViewHolder holder, UidPolicy up, ListItem item) {
            int i = data.indexOf(item);

            item.setItem1(policy.equals(UidPolicy.ALLOW) ? UidPolicy.DENY : UidPolicy.ALLOW);

            up.setPolicy(policy.equals(UidPolicy.ALLOW) ? UidPolicy.DENY : UidPolicy.ALLOW);

            SuDatabaseHelper.setPolicy(context, up);

            data.set(i, item);

            remove(holder.getAdapterPosition());
            callback.onListChanged(type);

            setEmpty();
        }

        private void revoke(final ViewHolder holder, final UidPolicy up, final ListItem item) {
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    if (msg.getData().getBoolean(DATA_BUNDLE_KEY)) {

                        data.remove(data.indexOf(item));

                        remove(holder.getAdapterPosition());

                        setEmpty();

                    } else
                        showErrorDialog(up, R.string.db_delete_error);
                }
            };

            new Thread() {
                public void run() {
                    final boolean done = SuDatabaseHelper.delete(getActivity(), up);
                    Message msg = handler.obtainMessage();
                    Bundle bundle = new Bundle();
                    bundle.putBoolean(DATA_BUNDLE_KEY, done);
                    msg.setData(bundle);
                    handler.sendMessage(msg);
                }
            }.start();
        }

        private void showErrorDialog(UidPolicy policy, int resource) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setTitle(policy.name)
                    .setIcon(Util.loadPackageIcon(getActivity(), policy.packageName))
                    .setMessage(getResources().getText(resource)).setCancelable(true)
                    .setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.dismiss();
                        }
                    });
            AlertDialog alert = builder.create();
            alert.show();
        }

        private void setClickListener(View view, final View icon, final ListItem item) {
            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(final View view) {
                    recycler.getHandler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            final Intent intent = new Intent(context, ActivityLog.class);

                            UidPolicy up = item.getPolicy();

                            if (up != null) {
                                Bundle args = new Bundle();
                                args.putString("name", up.getName());
                                args.putString("command", up.command);
                                args.putInt("uid", up.uid);
                                args.putInt("desiredUid", up.desiredUid);

                                intent.putExtra("bundle", args);

                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

                                    Pair<View, String> pair2 = Pair.create(icon, "icon");
                                    //Pair<View, String> pair1 = Pair.create(parent.findViewById(R.id.title), "title");

                                    ActivityOptionsCompat options = ActivityOptionsCompat
                                            .makeSceneTransitionAnimation(getActivity()/*, pair1*/, pair2);

                                    startActivity(intent, options.toBundle());

                                } else {
                                    startActivity(intent);
                                }
                            }
                        }
                    }, 200);
                }
            });
        }
    }
}