ManagePermissionsFragment.java revision f5f6b1b113bb39a268948c19a39833d3ff839d32
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.packageinstaller.permission.ui;
17
18import android.annotation.Nullable;
19import android.app.ActionBar;
20import android.app.FragmentTransaction;
21import android.content.ActivityNotFoundException;
22import android.content.Context;
23import android.content.Intent;
24import android.graphics.drawable.Drawable;
25import android.os.Bundle;
26import android.support.v7.preference.Preference;
27import android.support.v7.preference.Preference.OnPreferenceClickListener;
28import android.support.v7.preference.PreferenceScreen;
29import android.util.ArraySet;
30import android.util.Log;
31import android.view.Menu;
32import android.view.MenuInflater;
33import android.view.MenuItem;
34import android.view.View;
35import android.widget.ImageView;
36import android.widget.TextView;
37
38import com.android.packageinstaller.R;
39import com.android.packageinstaller.permission.model.PermissionApps;
40import com.android.packageinstaller.permission.model.PermissionApps.PmCache;
41import com.android.packageinstaller.permission.model.PermissionGroup;
42import com.android.packageinstaller.permission.model.PermissionGroups;
43import com.android.packageinstaller.permission.utils.Utils;
44
45import java.util.List;
46
47public final class ManagePermissionsFragment extends PermissionsFrameFragment
48        implements PermissionGroups.PermissionsGroupsChangeCallback, OnPreferenceClickListener {
49    private static final String LOG_TAG = "ManagePermissionsFragment";
50
51    private static final String OS_PKG = "android";
52
53    private static final String EXTRA_PREFS_KEY = "extra_prefs_key";
54
55    private ArraySet<String> mLauncherPkgs;
56
57    private PermissionGroups mPermissions;
58
59    private PreferenceScreen mExtraScreen;
60
61    private boolean mShowLegacyPermissions;
62
63    public static ManagePermissionsFragment newInstance() {
64        return new ManagePermissionsFragment();
65    }
66
67    @Override
68    public void onCreate(Bundle icicle) {
69        super.onCreate(icicle);
70        setLoading(true /* loading */, false /* animate */);
71        setHasOptionsMenu(true);
72        final ActionBar ab = getActivity().getActionBar();
73        if (ab != null) {
74            ab.setDisplayHomeAsUpEnabled(true);
75        }
76        mLauncherPkgs = Utils.getLauncherPackages(getContext());
77        mPermissions = new PermissionGroups(getActivity(), getLoaderManager(), this);
78    }
79
80    @Override
81    public void onResume() {
82        super.onResume();
83        mPermissions.refresh();
84        updatePermissionsUi();
85    }
86
87    @Override
88    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
89        super.onCreateOptionsMenu(menu, inflater);
90        inflater.inflate(R.menu.toggle_legacy_permissions, menu);
91    }
92
93    @Override
94    public void onPrepareOptionsMenu(Menu menu) {
95        MenuItem item = menu.findItem(R.id.toggle_legacy_permissions);
96        if (!mShowLegacyPermissions) {
97            item.setTitle(R.string.show_legacy_permissions);
98        } else {
99            item.setTitle(R.string.hide_legacy_permissions);
100        }
101    }
102
103    @Override
104    public boolean onOptionsItemSelected(MenuItem item) {
105        switch (item.getItemId()) {
106            case android.R.id.home: {
107                getActivity().finish();
108                return true;
109            }
110
111            case R.id.toggle_legacy_permissions: {
112                mShowLegacyPermissions = !mShowLegacyPermissions;
113                updatePermissionsUi();
114                return true;
115            }
116        }
117        return super.onOptionsItemSelected(item);
118    }
119
120    @Override
121    public boolean onPreferenceClick(Preference preference) {
122        String key = preference.getKey();
123
124        PermissionGroup group = mPermissions.getGroup(key);
125        if (group == null) {
126            return false;
127        }
128
129        Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
130                .putExtra(Intent.EXTRA_PERMISSION_NAME, key);
131        try {
132            getActivity().startActivity(intent);
133        } catch (ActivityNotFoundException e) {
134            Log.w(LOG_TAG, "No app to handle " + intent);
135        }
136
137        return true;
138    }
139
140    @Override
141    public void onPermissionGroupsChanged() {
142        updatePermissionsUi();
143    }
144
145    @Override
146    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
147        super.onViewCreated(view, savedInstanceState);
148        bindPermissionUi(getActivity(), getView());
149    }
150
151    private static void bindPermissionUi(@Nullable Context context, @Nullable View rootView) {
152        if (context == null || rootView == null) {
153            return;
154        }
155
156        ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon);
157        if (iconView != null) {
158            // Set the icon as the background instead of the image because ImageView
159            // doesn't properly scale vector drawables beyond their intrinsic size
160            Drawable icon = context.getDrawable(R.drawable.ic_lock);
161            icon.setTint(context.getColor(R.color.off_white));
162            iconView.setBackground(icon);
163        }
164        TextView titleView = (TextView) rootView.findViewById(R.id.lb_title);
165        if (titleView != null) {
166            titleView.setText(R.string.app_permissions);
167        }
168        TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb);
169        if (breadcrumbView != null) {
170            breadcrumbView.setText(R.string.app_permissions_breadcrumb);
171        }
172    }
173
174    private void updatePermissionsUi() {
175        Context context = getPreferenceManager().getContext();
176        if (context == null) {
177            return;
178        }
179
180        List<PermissionGroup> groups = mPermissions.getGroups();
181        PreferenceScreen screen = getPreferenceScreen();
182        boolean isTelevision = Utils.isTelevision(context);
183
184        // Use this to speed up getting the info for all of the PermissionApps below.
185        // Create a new one for each refresh to make sure it has fresh data.
186        PmCache cache = new PmCache(getContext().getPackageManager());
187        for (PermissionGroup group : groups) {
188            boolean isModernGroup = Utils.isModernPermissionGroup(group.getName());
189            boolean isSystemPermission = group.getDeclaringPackage().equals(OS_PKG);
190
191            // Show legacy permissions only if the user chose that, except
192            // on TV, where they get grouped into the extra screen.
193            if (!mShowLegacyPermissions && !isTelevision && isSystemPermission && !isModernGroup) {
194                continue;
195            }
196
197            Preference preference = findPreference(group.getName());
198            if (preference == null && mExtraScreen != null) {
199                preference = mExtraScreen.findPreference(group.getName());
200            }
201            if (preference == null) {
202                preference = new Preference(context);
203                preference.setOnPreferenceClickListener(this);
204                preference.setKey(group.getName());
205                preference.setIcon(Utils.applyTint(context, group.getIcon(),
206                        android.R.attr.colorControlNormal));
207                preference.setTitle(group.getLabel());
208                // Set blank summary so that no resizing/jumping happens when the summary is loaded.
209                preference.setSummary(" ");
210                preference.setPersistent(false);
211                if (isSystemPermission && (isModernGroup || !isTelevision)) {
212                    screen.addPreference(preference);
213                } else {
214                    if (mExtraScreen == null) {
215                        mExtraScreen = getPreferenceManager().createPreferenceScreen(context);
216                    }
217                    mExtraScreen.addPreference(preference);
218                }
219            }
220            final Preference finalPref = preference;
221
222            new PermissionApps(getContext(), group.getName(), new PermissionApps.Callback() {
223                @Override
224                public void onPermissionsLoaded(PermissionApps permissionApps) {
225                    if (getActivity() == null) {
226                        return;
227                    }
228                    int granted = permissionApps.getGrantedCount(mLauncherPkgs);
229                    int total = permissionApps.getTotalCount(mLauncherPkgs);
230                    finalPref.setSummary(getString(R.string.app_permissions_group_summary,
231                            granted, total));
232                }
233            }, cache).refresh(false);
234        }
235
236        if (mExtraScreen != null && mExtraScreen.getPreferenceCount() > 0
237                && screen.findPreference(EXTRA_PREFS_KEY) == null) {
238            Preference extraScreenPreference = new Preference(context);
239            extraScreenPreference.setKey(EXTRA_PREFS_KEY);
240            extraScreenPreference.setIcon(Utils.applyTint(context, R.drawable.ic_toc,
241                    android.R.attr.colorControlNormal));
242            extraScreenPreference.setTitle(R.string.additional_permissions);
243            extraScreenPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
244                @Override
245                public boolean onPreferenceClick(Preference preference) {
246                    AdditionalPermissionsFragment frag = new AdditionalPermissionsFragment();
247                    frag.setTargetFragment(ManagePermissionsFragment.this, 0);
248                    FragmentTransaction ft = getFragmentManager().beginTransaction();
249                    ft.replace(android.R.id.content, frag);
250                    ft.addToBackStack(null);
251                    ft.commit();
252                    return true;
253                }
254            });
255            int count = mExtraScreen.getPreferenceCount();
256            extraScreenPreference.setSummary(getResources().getQuantityString(
257                    R.plurals.additional_permissions_more, count, count));
258            screen.addPreference(extraScreenPreference);
259        }
260        if (screen.getPreferenceCount() != 0) {
261            setLoading(false /* loading */, true /* animate */);
262        }
263    }
264
265    public static class AdditionalPermissionsFragment extends PermissionsFrameFragment {
266        @Override
267        public void onCreate(Bundle icicle) {
268            setLoading(true /* loading */, false /* animate */);
269            super.onCreate(icicle);
270            getActivity().setTitle(R.string.additional_permissions);
271            setHasOptionsMenu(true);
272        }
273
274        @Override
275        public void onDestroy() {
276            getActivity().setTitle(R.string.app_permissions);
277            super.onDestroy();
278        }
279
280        @Override
281        public boolean onOptionsItemSelected(MenuItem item) {
282            switch (item.getItemId()) {
283                case android.R.id.home:
284                    getFragmentManager().popBackStack();
285                    return true;
286            }
287            return super.onOptionsItemSelected(item);
288        }
289
290        @Override
291        public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
292            super.onViewCreated(view, savedInstanceState);
293            bindPermissionUi(getActivity(), getView());
294        }
295
296        @Override
297        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
298            setPreferenceScreen(((ManagePermissionsFragment) getTargetFragment()).mExtraScreen);
299            setLoading(false /* loading */, true /* animate */);
300        }
301    }
302}
303