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 17 package com.android.settings.applications; 18 19 import android.app.Activity; 20 import android.app.AppOpsManager; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.pm.PackageInfo; 24 import android.content.pm.PackageManager; 25 import android.content.pm.PackageManager.NameNotFoundException; 26 import android.content.pm.PermissionGroupInfo; 27 import android.content.pm.PermissionInfo; 28 import android.content.res.Resources; 29 import android.graphics.drawable.Drawable; 30 import android.os.Bundle; 31 import android.text.TextUtils; 32 import android.util.Log; 33 import android.view.LayoutInflater; 34 import android.view.View; 35 import android.view.ViewGroup; 36 import android.widget.CompoundButton; 37 import android.widget.ImageView; 38 import android.widget.LinearLayout; 39 import android.widget.Switch; 40 import android.widget.TextView; 41 42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 43 import com.android.settings.core.InstrumentedPreferenceFragment; 44 import com.android.settings.R; 45 import com.android.settings.SettingsActivity; 46 import com.android.settings.Utils; 47 import com.android.settings.widget.EntityHeaderController; 48 49 import java.util.List; 50 51 public class AppOpsDetails extends InstrumentedPreferenceFragment { 52 static final String TAG = "AppOpsDetails"; 53 54 public static final String ARG_PACKAGE_NAME = "package"; 55 56 private AppOpsState mState; 57 private PackageManager mPm; 58 private AppOpsManager mAppOps; 59 private PackageInfo mPackageInfo; 60 private LayoutInflater mInflater; 61 private View mRootView; 62 private LinearLayout mOperationsSection; 63 64 // Utility method to set application label and icon. setAppLabelAndIcon(PackageInfo pkgInfo)65 private void setAppLabelAndIcon(PackageInfo pkgInfo) { 66 final View appSnippet = mRootView.findViewById(R.id.app_snippet); 67 CharSequence label = mPm.getApplicationLabel(pkgInfo.applicationInfo); 68 Drawable icon = mPm.getApplicationIcon(pkgInfo.applicationInfo); 69 setupAppSnippet(appSnippet, label, icon, 70 pkgInfo != null ? pkgInfo.versionName : null); 71 } 72 retrieveAppEntry()73 private String retrieveAppEntry() { 74 final Bundle args = getArguments(); 75 String packageName = (args != null) ? args.getString(ARG_PACKAGE_NAME) : null; 76 if (packageName == null) { 77 Intent intent = (args == null) ? 78 getActivity().getIntent() : (Intent) args.getParcelable("intent"); 79 if (intent != null) { 80 packageName = intent.getData().getSchemeSpecificPart(); 81 } 82 } 83 try { 84 mPackageInfo = mPm.getPackageInfo(packageName, 85 PackageManager.MATCH_DISABLED_COMPONENTS | 86 PackageManager.MATCH_ANY_USER); 87 } catch (NameNotFoundException e) { 88 Log.e(TAG, "Exception when retrieving package:" + packageName, e); 89 mPackageInfo = null; 90 } 91 92 return packageName; 93 } 94 refreshUi()95 private boolean refreshUi() { 96 if (mPackageInfo == null) { 97 return false; 98 } 99 100 setAppLabelAndIcon(mPackageInfo); 101 102 Resources res = getActivity().getResources(); 103 104 mOperationsSection.removeAllViews(); 105 String lastPermGroup = ""; 106 for (AppOpsState.OpsTemplate tpl : AppOpsState.ALL_TEMPLATES) { 107 List<AppOpsState.AppOpEntry> entries = mState.buildState(tpl, 108 mPackageInfo.applicationInfo.uid, mPackageInfo.packageName); 109 for (final AppOpsState.AppOpEntry entry : entries) { 110 final AppOpsManager.OpEntry firstOp = entry.getOpEntry(0); 111 final View view = mInflater.inflate(R.layout.app_ops_details_item, 112 mOperationsSection, false); 113 mOperationsSection.addView(view); 114 String perm = AppOpsManager.opToPermission(firstOp.getOp()); 115 if (perm != null) { 116 try { 117 PermissionInfo pi = mPm.getPermissionInfo(perm, 0); 118 if (pi.group != null && !lastPermGroup.equals(pi.group)) { 119 lastPermGroup = pi.group; 120 PermissionGroupInfo pgi = mPm.getPermissionGroupInfo(pi.group, 0); 121 if (pgi.icon != 0) { 122 ((ImageView)view.findViewById(R.id.op_icon)).setImageDrawable( 123 pgi.loadIcon(mPm)); 124 } 125 } 126 } catch (NameNotFoundException e) { 127 } 128 } 129 ((TextView)view.findViewById(R.id.op_name)).setText( 130 entry.getSwitchText(mState)); 131 ((TextView)view.findViewById(R.id.op_time)).setText( 132 entry.getTimeText(res, true)); 133 Switch sw = (Switch)view.findViewById(R.id.switchWidget); 134 final int switchOp = AppOpsManager.opToSwitch(firstOp.getOp()); 135 sw.setChecked(mAppOps.checkOp(switchOp, entry.getPackageOps().getUid(), 136 entry.getPackageOps().getPackageName()) == AppOpsManager.MODE_ALLOWED); 137 sw.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() { 138 @Override 139 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 140 mAppOps.setMode(switchOp, entry.getPackageOps().getUid(), 141 entry.getPackageOps().getPackageName(), isChecked 142 ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED); 143 } 144 }); 145 } 146 } 147 148 return true; 149 } 150 setIntentAndFinish(boolean finish, boolean appChanged)151 private void setIntentAndFinish(boolean finish, boolean appChanged) { 152 Intent intent = new Intent(); 153 intent.putExtra(ManageApplications.APP_CHG, appChanged); 154 SettingsActivity sa = (SettingsActivity)getActivity(); 155 sa.finishPreferencePanel(this, Activity.RESULT_OK, intent); 156 } 157 158 /** Called when the activity is first created. */ 159 @Override onCreate(Bundle icicle)160 public void onCreate(Bundle icicle) { 161 super.onCreate(icicle); 162 163 mState = new AppOpsState(getActivity()); 164 mPm = getActivity().getPackageManager(); 165 mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 166 mAppOps = (AppOpsManager)getActivity().getSystemService(Context.APP_OPS_SERVICE); 167 168 retrieveAppEntry(); 169 170 setHasOptionsMenu(true); 171 } 172 173 @Override onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)174 public View onCreateView( 175 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 176 final View view = inflater.inflate(R.layout.app_ops_details, container, false); 177 Utils.prepareCustomPreferencesList(container, view, view, false); 178 179 mRootView = view; 180 mOperationsSection = (LinearLayout)view.findViewById(R.id.operations_section); 181 return view; 182 } 183 184 @Override getMetricsCategory()185 public int getMetricsCategory() { 186 return MetricsEvent.APP_OPS_DETAILS; 187 } 188 189 @Override onResume()190 public void onResume() { 191 super.onResume(); 192 if (!refreshUi()) { 193 setIntentAndFinish(true, true); 194 } 195 } 196 197 /** 198 * @deprecated app info pages should use {@link EntityHeaderController} to show the app header. 199 */ setupAppSnippet(View appSnippet, CharSequence label, Drawable icon, CharSequence versionName)200 void setupAppSnippet(View appSnippet, CharSequence label, Drawable icon, 201 CharSequence versionName) { 202 LayoutInflater.from(appSnippet.getContext()).inflate(R.layout.widget_text_views, 203 appSnippet.findViewById(android.R.id.widget_frame)); 204 205 ImageView iconView = appSnippet.findViewById(android.R.id.icon); 206 iconView.setImageDrawable(icon); 207 // Set application name. 208 TextView labelView = appSnippet.findViewById(android.R.id.title); 209 labelView.setText(label); 210 // Version number of application 211 TextView appVersion = appSnippet.findViewById(R.id.widget_text1); 212 213 if (!TextUtils.isEmpty(versionName)) { 214 appVersion.setSelected(true); 215 appVersion.setVisibility(View.VISIBLE); 216 appVersion.setText(appSnippet.getContext().getString(R.string.version_text, 217 String.valueOf(versionName))); 218 } else { 219 appVersion.setVisibility(View.INVISIBLE); 220 } 221 } 222 } 223