1 /** 2 * Copyright (C) 2017 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 */ 16 17 package com.android.packageinstaller.permission.ui.auto; 18 19 20 import android.app.Activity; 21 import android.app.AlertDialog; 22 import android.app.Fragment; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.os.Bundle; 28 import android.support.annotation.DrawableRes; 29 import android.util.Log; 30 import android.view.LayoutInflater; 31 import android.view.MotionEvent; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.Switch; 35 import android.widget.Toast; 36 37 import com.android.car.list.IconToggleLineItem; 38 import com.android.car.list.TypedPagedListAdapter; 39 import com.android.packageinstaller.R; 40 import com.android.packageinstaller.permission.model.AppPermissionGroup; 41 import com.android.packageinstaller.permission.model.AppPermissions; 42 import com.android.packageinstaller.permission.utils.Utils; 43 44 import java.util.ArrayList; 45 46 import androidx.car.widget.PagedListView; 47 48 /** 49 * Contains all permissions in a list for a given application. 50 */ 51 public final class AppPermissionsFragment extends Fragment{ 52 53 private static final String LOG_TAG = "ManagePermsFragment"; 54 public static final String EXTRA_LAYOUT = "extra_layout"; 55 56 private AppPermissions mAppPermissions; 57 58 private String mPackageName; 59 60 protected PagedListView mListView; 61 protected TypedPagedListAdapter mPagedListAdapter; 62 63 64 /** 65 * Creates a new instance. 66 * @param packageName the packageName of the application that we are listing the 67 * permissions here. 68 */ newInstance(String packageName)69 public static AppPermissionsFragment newInstance(String packageName) { 70 AppPermissionsFragment fragment = new AppPermissionsFragment(); 71 Bundle arguments = new Bundle(); 72 arguments.putInt(EXTRA_LAYOUT, R.layout.car_app_permissions); 73 arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); 74 fragment.setArguments(arguments); 75 return fragment; 76 } 77 78 @Override onActivityCreated(Bundle savedInstanceState)79 public void onActivityCreated(Bundle savedInstanceState) { 80 super.onActivityCreated(savedInstanceState); 81 getView().findViewById(R.id.action_bar_icon_container).setOnClickListener( 82 v -> getActivity().onBackPressed()); 83 84 mListView = (PagedListView) getView().findViewById(R.id.list); 85 mPagedListAdapter = new TypedPagedListAdapter(getLineItems()); 86 mListView.setAdapter(mPagedListAdapter); 87 } 88 notifyDataSetChanged()89 protected void notifyDataSetChanged() { 90 mPagedListAdapter.notifyDataSetChanged(); 91 } 92 93 @Override onCreate(Bundle savedInstanceState)94 public void onCreate(Bundle savedInstanceState) { 95 super.onCreate(savedInstanceState); 96 if (savedInstanceState != null 97 && savedInstanceState.containsKey(Intent.EXTRA_PACKAGE_NAME)) { 98 mPackageName = savedInstanceState.getString(Intent.EXTRA_PACKAGE_NAME); 99 } else if (getArguments() != null 100 && getArguments().containsKey(Intent.EXTRA_PACKAGE_NAME)) { 101 mPackageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); 102 } 103 104 if (mPackageName == null) { 105 Log.e(LOG_TAG, "package name is missing"); 106 return; 107 } 108 Activity activity = getActivity(); 109 PackageInfo packageInfo = getPackageInfo(activity, mPackageName); 110 if (packageInfo == null) { 111 Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG).show(); 112 activity.finish(); 113 return; 114 } 115 116 mAppPermissions = new AppPermissions(activity, packageInfo, null, true, new Runnable() { 117 @Override 118 public void run() { 119 activity.finish(); 120 } 121 }); 122 } 123 124 @Override onSaveInstanceState(Bundle outState)125 public void onSaveInstanceState(Bundle outState) { 126 super.onSaveInstanceState(outState); 127 outState.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName); 128 } 129 130 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)131 public View onCreateView(LayoutInflater inflater, ViewGroup container, 132 Bundle savedInstanceState) { 133 return inflater.inflate(getArguments().getInt(EXTRA_LAYOUT), container, false); 134 } 135 136 @Override onResume()137 public void onResume() { 138 super.onResume(); 139 mAppPermissions.refresh(); 140 } 141 142 /** 143 * Gets the list of the LineItems to show up in the list 144 */ getLineItems()145 public ArrayList<TypedPagedListAdapter.LineItem> getLineItems() { 146 ArrayList<TypedPagedListAdapter.LineItem> items = new ArrayList<>(); 147 Context context = getContext(); 148 if (context == null) { 149 return items; 150 } 151 152 for (AppPermissionGroup group : mAppPermissions.getPermissionGroups()) { 153 if (!Utils.shouldShowPermission(group, mAppPermissions.getPackageInfo().packageName)) { 154 continue; 155 } 156 items.add(new PermissionLineItem(group, context)); 157 } 158 return items; 159 } 160 getPackageInfo(Activity activity, String packageName)161 private static PackageInfo getPackageInfo(Activity activity, String packageName) { 162 try { 163 return activity.getPackageManager().getPackageInfo( 164 packageName, PackageManager.GET_PERMISSIONS); 165 } catch (PackageManager.NameNotFoundException e) { 166 if (Log.isLoggable(LOG_TAG, Log.INFO)) { 167 Log.i(LOG_TAG, "No package:" + activity.getCallingPackage(), e); 168 } 169 return null; 170 } 171 } 172 173 private class PermissionLineItem extends IconToggleLineItem { 174 private final AppPermissionGroup mPermissionGroup; 175 private final Context mContext; 176 PermissionLineItem(AppPermissionGroup permissionGroup, Context context)177 PermissionLineItem(AppPermissionGroup permissionGroup, Context context) { 178 super(permissionGroup.getLabel(), context); 179 mContext = context; 180 mPermissionGroup = permissionGroup; 181 } 182 183 @Override onToggleTouched(Switch toggleSwitch, MotionEvent event)184 public boolean onToggleTouched(Switch toggleSwitch, MotionEvent event) { 185 if (event.getAction() != MotionEvent.ACTION_DOWN) { 186 return true; 187 } 188 if (!isChecked()) { 189 mPermissionGroup.grantRuntimePermissions(false); 190 toggleSwitch.performClick(); 191 } else { 192 final boolean grantedByDefault = 193 mPermissionGroup.hasGrantedByDefaultPermission(); 194 if (grantedByDefault || !mPermissionGroup.doesSupportRuntimePermissions()) { 195 new AlertDialog.Builder(mContext) 196 .setMessage(grantedByDefault 197 ? R.string.system_warning : R.string.old_sdk_deny_warning) 198 .setNegativeButton(R.string.cancel, null /* listener */) 199 .setPositiveButton(R.string.grant_dialog_button_deny_anyway, 200 (dialog, which) -> { 201 mPermissionGroup.revokeRuntimePermissions(false); 202 toggleSwitch.performClick(); 203 }) 204 .show(); 205 } else { 206 mPermissionGroup.revokeRuntimePermissions(false); 207 toggleSwitch.performClick(); 208 } 209 } 210 return true; 211 } 212 213 @DrawableRes getIcon()214 public int getIcon() { 215 return mPermissionGroup.getIconResId(); 216 } 217 218 @Override isChecked()219 public boolean isChecked() { 220 return mPermissionGroup.areRuntimePermissionsGranted(); 221 } 222 223 @Override getDesc()224 public CharSequence getDesc() { 225 return null; 226 } 227 228 @Override isEnabled()229 public boolean isEnabled() { 230 return true; 231 } 232 233 @Override isExpandable()234 public boolean isExpandable() { 235 return false; 236 } 237 } 238 } 239