1/**
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * 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, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package com.android.settings.applications;
18
19import android.app.Activity;
20import android.app.AppOpsManager;
21import android.app.Fragment;
22import android.content.Context;
23import android.content.Intent;
24import android.content.pm.PackageInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.PackageManager.NameNotFoundException;
27import android.content.pm.PermissionGroupInfo;
28import android.content.pm.PermissionInfo;
29import android.content.res.Resources;
30import android.os.Bundle;
31import android.preference.PreferenceActivity;
32import android.util.Log;
33import android.view.LayoutInflater;
34import android.view.View;
35import android.view.ViewGroup;
36import android.widget.CompoundButton;
37import android.widget.ImageView;
38import android.widget.LinearLayout;
39import android.widget.Switch;
40import android.widget.TextView;
41
42import com.android.settings.R;
43import com.android.settings.Utils;
44
45import java.util.List;
46
47public class AppOpsDetails extends Fragment {
48    static final String TAG = "AppOpsDetails";
49
50    public static final String ARG_PACKAGE_NAME = "package";
51
52    private AppOpsState mState;
53    private PackageManager mPm;
54    private AppOpsManager mAppOps;
55    private PackageInfo mPackageInfo;
56    private LayoutInflater mInflater;
57    private View mRootView;
58    private TextView mAppVersion;
59    private LinearLayout mOperationsSection;
60
61    // Utility method to set application label and icon.
62    private void setAppLabelAndIcon(PackageInfo pkgInfo) {
63        final View appSnippet = mRootView.findViewById(R.id.app_snippet);
64        appSnippet.setPaddingRelative(0, appSnippet.getPaddingTop(), 0, appSnippet.getPaddingBottom());
65
66        ImageView icon = (ImageView) appSnippet.findViewById(R.id.app_icon);
67        icon.setImageDrawable(mPm.getApplicationIcon(pkgInfo.applicationInfo));
68        // Set application name.
69        TextView label = (TextView) appSnippet.findViewById(R.id.app_name);
70        label.setText(mPm.getApplicationLabel(pkgInfo.applicationInfo));
71        // Version number of application
72        mAppVersion = (TextView) appSnippet.findViewById(R.id.app_size);
73
74        if (pkgInfo.versionName != null) {
75            mAppVersion.setVisibility(View.VISIBLE);
76            mAppVersion.setText(getActivity().getString(R.string.version_text,
77                    String.valueOf(pkgInfo.versionName)));
78        } else {
79            mAppVersion.setVisibility(View.INVISIBLE);
80        }
81    }
82
83    private String retrieveAppEntry() {
84        final Bundle args = getArguments();
85        String packageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null;
86        if (packageName == null) {
87            Intent intent = (args == null) ?
88                    getActivity().getIntent() : (Intent) args.getParcelable("intent");
89            if (intent != null) {
90                packageName = intent.getData().getSchemeSpecificPart();
91            }
92        }
93        try {
94            mPackageInfo = mPm.getPackageInfo(packageName,
95                    PackageManager.GET_DISABLED_COMPONENTS |
96                    PackageManager.GET_UNINSTALLED_PACKAGES);
97        } catch (NameNotFoundException e) {
98            Log.e(TAG, "Exception when retrieving package:" + packageName, e);
99            mPackageInfo = null;
100        }
101
102        return packageName;
103    }
104
105    private boolean refreshUi() {
106        if (mPackageInfo == null) {
107            return false;
108        }
109
110        setAppLabelAndIcon(mPackageInfo);
111
112        Resources res = getActivity().getResources();
113
114        mOperationsSection.removeAllViews();
115        String lastPermGroup = "";
116        for (AppOpsState.OpsTemplate tpl : AppOpsState.ALL_TEMPLATES) {
117            List<AppOpsState.AppOpEntry> entries = mState.buildState(tpl,
118                    mPackageInfo.applicationInfo.uid, mPackageInfo.packageName);
119            for (final AppOpsState.AppOpEntry entry : entries) {
120                final AppOpsManager.OpEntry firstOp = entry.getOpEntry(0);
121                final View view = mInflater.inflate(R.layout.app_ops_details_item,
122                        mOperationsSection, false);
123                mOperationsSection.addView(view);
124                String perm = AppOpsManager.opToPermission(firstOp.getOp());
125                if (perm != null) {
126                    try {
127                        PermissionInfo pi = mPm.getPermissionInfo(perm, 0);
128                        if (pi.group != null && !lastPermGroup.equals(pi.group)) {
129                            lastPermGroup = pi.group;
130                            PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(pi.group, 0);
131                            if (pgi.icon != 0) {
132                                ((ImageView)view.findViewById(R.id.op_icon)).setImageDrawable(
133                                        pgi.loadIcon(mPm));
134                            }
135                        }
136                    } catch (NameNotFoundException e) {
137                    }
138                }
139                ((TextView)view.findViewById(R.id.op_name)).setText(
140                        entry.getSwitchText(mState));
141                ((TextView)view.findViewById(R.id.op_time)).setText(
142                        entry.getTimeText(res, true));
143                Switch sw = (Switch)view.findViewById(R.id.switchWidget);
144                final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp());
145                sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(),
146                        entry.getPackageOps().getPackageName()) == AppOpsManager.MODE_ALLOWED);
147                sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
148                    @Override
149                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
150                        mAppOps.setMode(switchOp, entry.getPackageOps().getUid(),
151                                entry.getPackageOps().getPackageName(), isChecked
152                                ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
153                    }
154                });
155            }
156        }
157
158        return true;
159    }
160
161    private void setIntentAndFinish(boolean finish, boolean appChanged) {
162        Intent intent = new Intent();
163        intent.putExtra(ManageApplications.APP_CHG, appChanged);
164        PreferenceActivity pa = (PreferenceActivity)getActivity();
165        pa.finishPreferencePanel(this, Activity.RESULT_OK, intent);
166    }
167
168    /** Called when the activity is first created. */
169    @Override
170    public void onCreate(Bundle icicle) {
171        super.onCreate(icicle);
172
173        mState = new AppOpsState(getActivity());
174        mPm = getActivity().getPackageManager();
175        mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
176        mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE);
177
178        retrieveAppEntry();
179
180        setHasOptionsMenu(true);
181    }
182
183    @Override
184    public View onCreateView(
185            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
186        final View view = inflater.inflate(R.layout.app_ops_details, container, false);
187        Utils.prepareCustomPreferencesList(container, view, view, false);
188
189        mRootView = view;
190        mOperationsSection = (LinearLayout)view.findViewById(R.id.operations_section);
191        return view;
192    }
193
194    @Override
195    public void onResume() {
196        super.onResume();
197        if (!refreshUi()) {
198            setIntentAndFinish(true, true);
199        }
200    }
201}
202