118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn/**
218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Copyright (C) 2013 The Android Open Source Project
318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn *
418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); you may not
518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * use this file except in compliance with the License. You may obtain a copy
618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * of the License at
718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn *
818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0
918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn *
1018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
1118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * License for the specific language governing permissions and limitations
1418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * under the License.
1518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn */
1618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
1718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornpackage com.android.settings.applications;
1818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
190dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.app.Activity;
200dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.app.AppOpsManager;
2118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.app.Fragment;
220dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.Context;
230dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.Intent;
240dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.pm.PackageInfo;
250dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.pm.PackageManager;
260dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException;
270dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.pm.PermissionGroupInfo;
280dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.pm.PermissionInfo;
290dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.content.res.Resources;
300dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.os.Bundle;
310dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.util.Log;
320dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.view.LayoutInflater;
330dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.view.View;
340dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.view.ViewGroup;
350dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.widget.CompoundButton;
360dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.widget.ImageView;
370dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.widget.LinearLayout;
380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.widget.Switch;
390dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.widget.TextView;
400dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
410dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport com.android.settings.R;
42263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglioimport com.android.settings.SettingsActivity;
430dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport com.android.settings.Utils;
440dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
450dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport java.util.List;
4618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
4718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornpublic class AppOpsDetails extends Fragment {
480dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    static final String TAG = "AppOpsDetails";
490dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
500dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    public static final String ARG_PACKAGE_NAME = "package";
510dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
520dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private AppOpsState mState;
530dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private PackageManager mPm;
540dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private AppOpsManager mAppOps;
550dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private PackageInfo mPackageInfo;
560dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private LayoutInflater mInflater;
570dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private View mRootView;
580dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private TextView mAppVersion;
590dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private LinearLayout mOperationsSection;
600dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
610dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    // Utility method to set application label and icon.
620dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private void setAppLabelAndIcon(PackageInfo pkgInfo) {
630dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        final View appSnippet = mRootView.findViewById(R.id.app_snippet);
640dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        appSnippet.setPaddingRelative(0, appSnippet.getPaddingTop(), 0, appSnippet.getPaddingBottom());
650dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
660dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        ImageView icon = (ImageView) appSnippet.findViewById(R.id.app_icon);
670dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        icon.setImageDrawable(mPm.getApplicationIcon(pkgInfo.applicationInfo));
680dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        // Set application name.
690dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        TextView label = (TextView) appSnippet.findViewById(R.id.app_name);
700dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        label.setText(mPm.getApplicationLabel(pkgInfo.applicationInfo));
710dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        // Version number of application
720dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mAppVersion = (TextView) appSnippet.findViewById(R.id.app_size);
730dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
740dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (pkgInfo.versionName != null) {
750dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mAppVersion.setVisibility(View.VISIBLE);
760dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mAppVersion.setText(getActivity().getString(R.string.version_text,
770dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    String.valueOf(pkgInfo.versionName)));
780dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        } else {
790dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mAppVersion.setVisibility(View.INVISIBLE);
800dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
810dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
820dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
830dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private String retrieveAppEntry() {
840dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        final Bundle args = getArguments();
850dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        String packageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
860dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (packageName == null) {
870dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            Intent intent = (args == null) ?
880dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    getActivity().getIntent() : (Intent) args.getParcelable("intent");
890dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            if (intent != null) {
900dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                packageName = intent.getData().getSchemeSpecificPart();
910dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            }
920dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
930dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        try {
940dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mPackageInfo = mPm.getPackageInfo(packageName,
950dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    PackageManager.GET_DISABLED_COMPONENTS |
960dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    PackageManager.GET_UNINSTALLED_PACKAGES);
970dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        } catch (NameNotFoundException e) {
980dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            Log.e(TAG, "Exception when retrieving package:" + packageName, e);
990dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mPackageInfo = null;
1000dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
1010dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1020dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        return packageName;
1030dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
1040dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1050dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private boolean refreshUi() {
1060dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (mPackageInfo == null) {
1070dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            return false;
1080dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
1090dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1100dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        setAppLabelAndIcon(mPackageInfo);
1110dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1120dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        Resources res = getActivity().getResources();
1130dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1140dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mOperationsSection.removeAllViews();
1150dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        String lastPermGroup = "";
1160dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        for (AppOpsState.OpsTemplate tpl : AppOpsState.ALL_TEMPLATES) {
1170dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            List<AppOpsState.AppOpEntry> entries = mState.buildState(tpl,
1180dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    mPackageInfo.applicationInfo.uid, mPackageInfo.packageName);
1190dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            for (final AppOpsState.AppOpEntry entry : entries) {
12027daaab633a80be50863e6539e947db674090662Dianne Hackborn                final AppOpsManager.OpEntry firstOp = entry.getOpEntry(0);
12127daaab633a80be50863e6539e947db674090662Dianne Hackborn                final View view = mInflater.inflate(R.layout.app_ops_details_item,
12227daaab633a80be50863e6539e947db674090662Dianne Hackborn                        mOperationsSection, false);
12327daaab633a80be50863e6539e947db674090662Dianne Hackborn                mOperationsSection.addView(view);
12427daaab633a80be50863e6539e947db674090662Dianne Hackborn                String perm = AppOpsManager.opToPermission(firstOp.getOp());
12527daaab633a80be50863e6539e947db674090662Dianne Hackborn                if (perm != null) {
12627daaab633a80be50863e6539e947db674090662Dianne Hackborn                    try {
12727daaab633a80be50863e6539e947db674090662Dianne Hackborn                        PermissionInfo pi = mPm.getPermissionInfo(perm, 0);
12827daaab633a80be50863e6539e947db674090662Dianne Hackborn                        if (pi.group != null && !lastPermGroup.equals(pi.group)) {
12927daaab633a80be50863e6539e947db674090662Dianne Hackborn                            lastPermGroup = pi.group;
13027daaab633a80be50863e6539e947db674090662Dianne Hackborn                            PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(pi.group, 0);
13127daaab633a80be50863e6539e947db674090662Dianne Hackborn                            if (pgi.icon != 0) {
13227daaab633a80be50863e6539e947db674090662Dianne Hackborn                                ((ImageView)view.findViewById(R.id.op_icon)).setImageDrawable(
13327daaab633a80be50863e6539e947db674090662Dianne Hackborn                                        pgi.loadIcon(mPm));
1340dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                            }
1350dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                        }
13627daaab633a80be50863e6539e947db674090662Dianne Hackborn                    } catch (NameNotFoundException e) {
1370dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    }
1380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                }
13927daaab633a80be50863e6539e947db674090662Dianne Hackborn                ((TextView)view.findViewById(R.id.op_name)).setText(
1408b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                        entry.getSwitchText(mState));
14127daaab633a80be50863e6539e947db674090662Dianne Hackborn                ((TextView)view.findViewById(R.id.op_time)).setText(
1428b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                        entry.getTimeText(res, true));
14327daaab633a80be50863e6539e947db674090662Dianne Hackborn                Switch sw = (Switch)view.findViewById(R.id.switchWidget);
14427daaab633a80be50863e6539e947db674090662Dianne Hackborn                final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
14527daaab633a80be50863e6539e947db674090662Dianne Hackborn                sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
14627daaab633a80be50863e6539e947db674090662Dianne Hackborn                        entry.getPackageOps().getPackageName()) == AppOpsManager.MODE_ALLOWED);
14727daaab633a80be50863e6539e947db674090662Dianne Hackborn                sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
14827daaab633a80be50863e6539e947db674090662Dianne Hackborn                    @Override
14927daaab633a80be50863e6539e947db674090662Dianne Hackborn                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
15027daaab633a80be50863e6539e947db674090662Dianne Hackborn                        mAppOps.setMode(switchOp, entry.getPackageOps().getUid(),
15127daaab633a80be50863e6539e947db674090662Dianne Hackborn                                entry.getPackageOps().getPackageName(), isChecked
15227daaab633a80be50863e6539e947db674090662Dianne Hackborn                                ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
15327daaab633a80be50863e6539e947db674090662Dianne Hackborn                    }
15427daaab633a80be50863e6539e947db674090662Dianne Hackborn                });
1550dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            }
1560dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
1570dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1580dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        return true;
1590dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
1600dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1610dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private void setIntentAndFinish(boolean finish, boolean appChanged) {
1620dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        Intent intent = new Intent();
1630dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        intent.putExtra(ManageApplications.APP_CHG, appChanged);
164263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        SettingsActivity sa = (SettingsActivity)getActivity();
165263bcc8b732dbb47d3ce63904e0e05191fabbad6Fabrice Di Meglio        sa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
1660dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
1670dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1680dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    /** Called when the activity is first created. */
1690dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    @Override
1700dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    public void onCreate(Bundle icicle) {
1710dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        super.onCreate(icicle);
1720dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1730dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mState = new AppOpsState(getActivity());
1740dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mPm = getActivity().getPackageManager();
1750dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1760dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE);
1770dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1780dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        retrieveAppEntry();
1790dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1800dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        setHasOptionsMenu(true);
1810dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
1820dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1830dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    @Override
1840dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    public View onCreateView(
1850dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
1860dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        final View view = inflater.inflate(R.layout.app_ops_details, container, false);
1870dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        Utils.prepareCustomPreferencesList(container, view, view, false);
1880dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
1890dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mRootView = view;
1900dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        mOperationsSection = (LinearLayout)view.findViewById(R.id.operations_section);
1910dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        return view;
1920dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
19318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
1940dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    @Override
1950dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    public void onResume() {
1960dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        super.onResume();
1970dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (!refreshUi()) {
1980dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            setIntentAndFinish(true, true);
1990dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
2000dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
20118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn}
202