diff options
Diffstat (limited to 'src/com/android/packageinstaller/permission/ui')
6 files changed, 889 insertions, 0 deletions
diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java new file mode 100644 index 00000000..a74f08c8 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java @@ -0,0 +1,198 @@ +/* +* Copyright (C) 2015 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package com.android.packageinstaller.permission.ui; + +import android.annotation.Nullable; +import android.app.ActionBar; +import android.app.Activity; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.utils.Utils; +import com.android.packageinstaller.permission.model.AppPermissions; +import com.android.packageinstaller.permission.model.PermissionGroup; + +public final class AppPermissionsFragment extends SettingsWithHeader + implements OnPreferenceChangeListener { + private static final String LOG_TAG = "ManagePermsFragment"; + + private AppPermissions mAppPermissions; + + public static AppPermissionsFragment newInstance(String packageName) { + AppPermissionsFragment instance = new AppPermissionsFragment(); + Bundle arguments = new Bundle(); + arguments.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + instance.setArguments(arguments); + return instance; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + final ActionBar ab = getActivity().getActionBar(); + if (ab != null) { + ab.setDisplayHomeAsUpEnabled(true); + } + } + + @Override + public void onResume() { + super.onResume(); + updateUi(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + getActivity().finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, + false); + ViewGroup prefsContainer = (ViewGroup) rootView.findViewById(R.id.prefs_container); + if (prefsContainer == null) { + prefsContainer = rootView; + } + prefsContainer.addView(super.onCreateView(inflater, prefsContainer, savedInstanceState)); + View emptyView = rootView.findViewById(R.id.no_permissions); + ((ListView) rootView.findViewById(android.R.id.list)).setEmptyView(emptyView); + return rootView; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + bindUi(); + } + + private void bindUi() { + String packageName = getArguments().getString(Intent.EXTRA_PACKAGE_NAME); + + final Activity activity = getActivity(); + PackageInfo packageInfo = getPackageInfo(packageName); + if (packageInfo == null) { + Toast.makeText(activity, R.string.app_not_found_dlg_title, Toast.LENGTH_LONG) + .show(); + activity.finish(); + return; + } + final PackageManager pm = activity.getPackageManager(); + ApplicationInfo appInfo = packageInfo.applicationInfo; + final Drawable icon = appInfo.loadIcon(pm); + final CharSequence label = appInfo.loadLabel(pm); + setHeader(icon, label, null); + + final ViewGroup rootView = (ViewGroup) getView(); + final ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon); + if (iconView != null) { + iconView.setImageDrawable(icon); + } + final TextView titleView = (TextView) rootView.findViewById(R.id.lb_title); + if (titleView != null) { + titleView.setText(R.string.app_permissions); + } + final TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb); + if (breadcrumbView != null) { + breadcrumbView.setText(label); + } + + PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(activity); + mAppPermissions = new AppPermissions(activity, packageInfo, null); + + for (PermissionGroup group : mAppPermissions.getPermissionGroups()) { + SwitchPreference preference = new SwitchPreference(activity); + preference.setOnPreferenceChangeListener(this); + preference.setKey(group.getName()); + preference.setIcon(Utils.loadDrawable(pm, group.getIconPkg(), + group.getIconResId())); + preference.setTitle(group.getLabel()); + preference.setPersistent(false); + screen.addPreference(preference); + } + + setPreferenceScreen(screen); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String groupName = preference.getKey(); + PermissionGroup group = mAppPermissions.getPermissionGroup(groupName); + + if (group == null) { + return false; + } + + if (newValue == Boolean.TRUE) { + group.grantRuntimePermissions(); + } else { + group.revokeRuntimePermissions(); + } + + return true; + } + + private void updateUi() { + mAppPermissions.refresh(); + + final int preferenceCount = getPreferenceScreen().getPreferenceCount(); + for (int i = 0; i < preferenceCount; i++) { + SwitchPreference preference = (SwitchPreference) + getPreferenceScreen().getPreference(i); + PermissionGroup group = mAppPermissions + .getPermissionGroup(preference.getKey()); + if (group != null) { + preference.setChecked(group.areRuntimePermissionsGranted()); + } + } + } + + private PackageInfo getPackageInfo(String packageName) { + try { + return getActivity().getPackageManager().getPackageInfo( + packageName, PackageManager.GET_PERMISSIONS); + } catch (PackageManager.NameNotFoundException e) { + Log.i(LOG_TAG, "No package:" + getActivity().getCallingPackage(), e); + return null; + } + } +}
\ No newline at end of file diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java new file mode 100644 index 00000000..0458f9b9 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionFragment.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller.permission.ui; + +import android.app.Activity; +import android.app.DialogFragment; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.utils.Utils; + +public final class GrantPermissionFragment extends DialogFragment { + public static final String ARG_GROUP_NAME = "ARG_GROUP_NAME"; + public static final String ARG_GROUP_COUNT = "ARG_GROUP_COUNT"; + public static final String ARG_GROUP_INDEX = "ARG_GROUP_INDEX"; + public static final String ARG_GROUP_ICON_RES_ID = "ARG_GROUP_ICON"; + public static final String ARG_GROUP_ICON_PKG = "ARG_GROUP_ICON_PKG"; + public static final String ARG_GROUP_MESSAGE = "ARG_GROUP_MESSAGE"; + + public interface OnRequestGrantPermissionGroupResult { + public void onRequestGrantPermissionGroupResult(String name, boolean granted); + } + + public static GrantPermissionFragment newInstance(String groupName, int groupCount, + int groupIndex, String iconPkg, int iconResId, CharSequence message) { + GrantPermissionFragment instance = new GrantPermissionFragment(); + instance.setStyle(STYLE_NORMAL, + android.R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar); + + Bundle arguments = new Bundle(); + arguments.putString(ARG_GROUP_NAME, groupName); + arguments.putInt(ARG_GROUP_COUNT, groupCount); + arguments.putInt(ARG_GROUP_INDEX, groupIndex); + arguments.putInt(ARG_GROUP_ICON_RES_ID, iconResId); + arguments.putString(ARG_GROUP_ICON_PKG, iconPkg); + arguments.putCharSequence(ARG_GROUP_MESSAGE, message); + instance.setArguments(arguments); + + return instance; + } + + private String mGroupName; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View content = inflater.inflate(R.layout.grant_permissions, container, false); + + mGroupName = getArguments().getString(ARG_GROUP_NAME); + final CharSequence message = getArguments().getCharSequence(ARG_GROUP_MESSAGE); + final String iconPkg = getArguments().getString(ARG_GROUP_ICON_PKG); + final int iconResId = getArguments().getInt(ARG_GROUP_ICON_RES_ID); + final int groupCount = getArguments().getInt(ARG_GROUP_COUNT); + final int groupIndex = getArguments().getInt(ARG_GROUP_INDEX); + + final ImageView iconView = (ImageView) content.findViewById(R.id.permission_icon); + final View allowButton = content.findViewById(R.id.permission_allow_button); + final View denyButton = content.findViewById(R.id.permission_deny_button); + final View doNotAskCheckbox = content.findViewById(R.id.do_not_ask_checkbox); + final TextView currentGroupView = (TextView) content.findViewById(R.id.current_page_text); + final TextView messageView = (TextView) content.findViewById(R.id.permission_message); + + OnClickListener clickListener = new OnClickListener() { + @Override + public void onClick(View view) { + if (view == allowButton) { + ((OnRequestGrantPermissionGroupResult) getActivity()) + .onRequestGrantPermissionGroupResult(mGroupName, true); + } else if (view == denyButton) { + ((OnRequestGrantPermissionGroupResult) getActivity()) + .onRequestGrantPermissionGroupResult(mGroupName, false); + } else if (view == doNotAskCheckbox) { + //TODO: Implement me. + } + } + }; + + Drawable icon = Utils.loadDrawable(getActivity().getPackageManager(), iconPkg, + iconResId); + iconView.setImageDrawable(icon); + + messageView.setText(message); + + allowButton.setOnClickListener(clickListener); + denyButton.setOnClickListener(clickListener); + doNotAskCheckbox.setOnClickListener(clickListener); + + if (groupCount > 1) { + currentGroupView.setVisibility(View.VISIBLE); + currentGroupView.setText(getString(R.string.current_permission_template, + groupIndex + 1, groupCount)); + } else { + currentGroupView.setVisibility(View.INVISIBLE); + } + + return content; + } + + @Override + public void onDismiss(DialogInterface dialog) { + Activity activity = getActivity(); + if (activity != null) { + ((OnRequestGrantPermissionGroupResult) getActivity()) + .onRequestGrantPermissionGroupResult(mGroupName, false); + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java new file mode 100644 index 00000000..02951e9f --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller.permission.ui; + +import android.app.Activity; +import android.app.DialogFragment; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.PermissionInfo; +import android.hardware.camera2.utils.ArrayUtils; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.util.ArrayMap; +import android.util.Log; +import android.util.SparseArray; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.AppPermissions; +import com.android.packageinstaller.permission.model.Permission; +import com.android.packageinstaller.permission.model.PermissionGroup; + +public class GrantPermissionsActivity extends Activity implements + GrantPermissionFragment.OnRequestGrantPermissionGroupResult { + private static final String LOG_TAG = "GrantPermissionsActivity"; + + private static final String TAG_GRANT_PERMISSION_GROUP_FRAGMENT = + "TAG_GRANT_PERMISSION_GROUP_FRAGMENT"; + + private static final int PERMISSION_GRANTED = 1; + private static final int PERMISSION_DENIED = 2; + private static final int PERMISSION_DENIED_RUNTIME = 3; + + private String[] mRequestedPermissions; + private int[] mGrantResults; + private final SparseArray<String> mRequestedRuntimePermissions = new SparseArray<>(); + + private ArrayMap<String, GroupState> mRequestGrantPermissionGroups = new ArrayMap<>(); + + private AppPermissions mAppPermissions; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mRequestedPermissions = getIntent().getStringArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); + if (mRequestedPermissions == null) { + mRequestedPermissions = new String[0]; + } + + mGrantResults = new int[mRequestedPermissions.length]; + + final int requestedPermCount = mRequestedPermissions.length; + if (requestedPermCount == 0) { + setResultAndFinish(); + return; + } + + PackageInfo callingPackageInfo = getCallingPackageInfo(); + if (callingPackageInfo == null) { + setResultAndFinish(); + return; + } + + updateDefaultResults(callingPackageInfo); + + mAppPermissions = new AppPermissions(this, callingPackageInfo, mRequestedPermissions); + + for (PermissionGroup group : mAppPermissions.getPermissionGroups()) { + if (!group.areRuntimePermissionsGranted()) { + mRequestGrantPermissionGroups.put(group.getName(), new GroupState(group)); + } + } + + if (!showNextPermissionGroupFragment()) { + setResultAndFinish(); + } + } + + private boolean showNextPermissionGroupFragment() { + final int groupCount = mRequestGrantPermissionGroups.size(); + + for (int i = 0; i < groupCount; i++) { + GroupState groupState = mRequestGrantPermissionGroups.valueAt(i); + if (!groupState.mGroup.areRuntimePermissionsGranted() + && groupState.mState == GroupState.STATE_UNKNOWN) { + // Make sure adding the fragment we will remove is not in flight. + getFragmentManager().executePendingTransactions(); + + // Remove old grant fragment if such exists. + FragmentTransaction transaction = getFragmentManager().beginTransaction(); + Fragment oldFragment = getFragmentManager().findFragmentByTag( + TAG_GRANT_PERMISSION_GROUP_FRAGMENT); + if (oldFragment != null) { + transaction.remove(oldFragment); + } + transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); + transaction.commit(); + + CharSequence appLabel = mAppPermissions.getAppLabel(); + SpannableString message = new SpannableString(getString( + R.string.permission_warning_template, appLabel, + groupState.mGroup.getLabel())); + // Bold/color the app name. + int appLabelStart = message.toString().indexOf(appLabel.toString(), 0); + int appLabelLength = appLabel.length(); + int color = getResources().getColor(R.color.grant_permissions_app_color, null); + message.setSpan(new ForegroundColorSpan(color), appLabelStart, + appLabelStart + appLabelLength, 0); + + // Add the new grant fragment. + // TODO: Use a real message for the action. We need group action APIs + String pkg = groupState.mGroup.getIconPkg(); + int icon = groupState.mGroup.getIconResId(); + DialogFragment newFragment = GrantPermissionFragment + .newInstance(groupState.mGroup.getName(), groupCount, i, + pkg, icon, message); + + newFragment.show(getFragmentManager(), TAG_GRANT_PERMISSION_GROUP_FRAGMENT); + return true; + } + } + + return false; + } + + @Override + public void onRequestGrantPermissionGroupResult(String name, boolean granted) { + GroupState groupState = mRequestGrantPermissionGroups.get(name); + if (groupState.mGroup != null) { + if (granted) { + groupState.mGroup.grantRuntimePermissions(); + groupState.mState = GroupState.STATE_ALLOWED; + updateGrantResults(groupState.mGroup); + } else { + groupState.mState = GroupState.STATE_DENIED; + } + } + if (!showNextPermissionGroupFragment()) { + setResultAndFinish(); + } + } + + private void updateGrantResults(PermissionGroup group) { + for (Permission permission : group.getPermissions()) { + if (permission.isGranted()) { + final int index = ArrayUtils.getArrayIndex( + mRequestedPermissions, permission.getName()); + if (index >= 0) { + mGrantResults[index] = PackageManager.PERMISSION_GRANTED; + } + } + } + } + + private int computePermissionGrantState(PackageInfo callingPackageInfo, String permission) { + boolean permissionRequested = false; + + for (int i = 0; i < callingPackageInfo.requestedPermissions.length; i++) { + if (permission.equals(callingPackageInfo.requestedPermissions[i])) { + permissionRequested = true; + if ((callingPackageInfo.requestedPermissionsFlags[i] + & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) { + return PERMISSION_GRANTED; + } + break; + } + } + + if (!permissionRequested) { + return PERMISSION_DENIED; + } + + try { + PermissionInfo pInfo = getPackageManager().getPermissionInfo(permission, 0); + if ((pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + != PermissionInfo.PROTECTION_DANGEROUS) { + return PERMISSION_DENIED; + } + } catch (NameNotFoundException e) { + /* ignore */ + } + + return PERMISSION_DENIED_RUNTIME; + } + + private PackageInfo getCallingPackageInfo() { + try { + return getPackageManager().getPackageInfo(getCallingPackage(), + PackageManager.GET_PERMISSIONS); + } catch (NameNotFoundException e) { + Log.i(LOG_TAG, "No package:" + getCallingPackage(), e); + return null; + } + } + + private void updateDefaultResults(PackageInfo callingPackageInfo) { + final int requestedPermCount = mRequestedPermissions.length; + for (int i = 0; i < requestedPermCount; i++) { + String permission = mRequestedPermissions[i]; + final int state = computePermissionGrantState(callingPackageInfo, permission); + switch (state) { + case PERMISSION_GRANTED: { + mGrantResults[i] = PackageManager.PERMISSION_GRANTED; + } break; + + case PERMISSION_DENIED: { + mGrantResults[i] = PackageManager.PERMISSION_DENIED; + } break; + + case PERMISSION_DENIED_RUNTIME: { + mGrantResults[i] = PackageManager.PERMISSION_DENIED; + mRequestedRuntimePermissions.put(i, permission); + } break; + } + } + } + + private void setResultAndFinish() { + Intent result = new Intent(PackageManager.ACTION_REQUEST_PERMISSIONS); + result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, mRequestedPermissions); + result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, mGrantResults); + setResult(RESULT_OK, result); + finish(); + } + + private static final class GroupState { + public static final int STATE_UNKNOWN = 0; + public static final int STATE_ALLOWED = 1; + public static final int STATE_DENIED = 2; + + public final PermissionGroup mGroup; + public int mState = STATE_UNKNOWN; + + public GroupState(PermissionGroup group) { + mGroup = group; + } + } +} diff --git a/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java new file mode 100644 index 00000000..ef117a9c --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/ManagePermissionsActivity.java @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2015 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package com.android.packageinstaller.permission.ui; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +public final class ManagePermissionsActivity extends Activity { + private static final String LOG_TAG = "ManagePermissionsActivity"; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + Fragment fragment = null; + String action = getIntent().getAction(); + if (Intent.ACTION_MANAGE_APP_PERMISSIONS.equals(action)) { + String packageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); + if (packageName == null) { + Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PACKAGE_NAME"); + finish(); + return; + } + fragment = AppPermissionsFragment.newInstance(packageName); + } else if (Intent.ACTION_MANAGE_PERMISSION_APPS.equals(action)) { + String permissionName = getIntent().getStringExtra(Intent.EXTRA_PERMISSION_NAME); + if (permissionName == null) { + Log.i(LOG_TAG, "Missing mandatory argument EXTRA_PERMISSION_NAME"); + finish(); + return; + } + fragment = PermissionAppsFragment.newInstance(permissionName); + } else { + Log.w(LOG_TAG, "Unrecognized action " + action); + finish(); + return; + } + + getFragmentManager().beginTransaction().replace(android.R.id.content, fragment).commit(); + } +} diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java new file mode 100644 index 00000000..f5d7d711 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.packageinstaller.permission.ui; + +import android.annotation.Nullable; +import android.app.ActionBar; +import android.content.Context; +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceScreen; +import android.preference.SwitchPreference; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.android.packageinstaller.R; +import com.android.packageinstaller.permission.model.PermissionApps; +import com.android.packageinstaller.permission.model.PermissionApps.Callback; +import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp; + +public final class PermissionAppsFragment extends SettingsWithHeader implements Callback, + OnPreferenceChangeListener { + + public static PermissionAppsFragment newInstance(String permissionName) { + PermissionAppsFragment instance = new PermissionAppsFragment(); + Bundle arguments = new Bundle(); + arguments.putString(Intent.EXTRA_PERMISSION_NAME, permissionName); + instance.setArguments(arguments); + return instance; + } + + private PermissionApps mPermissionApps; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + final ActionBar ab = getActivity().getActionBar(); + if (ab != null) { + ab.setDisplayHomeAsUpEnabled(true); + } + } + + @Override + public void onResume() { + super.onResume(); + mPermissionApps.refresh(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + getActivity().finish(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.permissions_frame, container, + false); + ViewGroup prefsContainer = (ViewGroup) rootView.findViewById(R.id.prefs_container); + if (prefsContainer == null) { + prefsContainer = rootView; + } + prefsContainer.addView(super.onCreateView(inflater, prefsContainer, savedInstanceState)); + View emptyView = rootView.findViewById(R.id.no_permissions); + if (emptyView != null) { + emptyView.setVisibility(View.GONE); + } + return rootView; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + bindUi(); + } + + private void bindUi() { + String groupName = getArguments().getString(Intent.EXTRA_PERMISSION_NAME); + mPermissionApps = new PermissionApps(getActivity(), groupName, this); + final Drawable icon = mPermissionApps.getIcon(); + final CharSequence label = mPermissionApps.getLabel(); + setHeader(icon, label, null); + + final ViewGroup rootView = (ViewGroup) getView(); + final ImageView iconView = (ImageView) rootView.findViewById(R.id.lb_icon); + if (iconView != null) { + iconView.setImageDrawable(icon); + } + final TextView titleView = (TextView) rootView.findViewById(R.id.lb_title); + if (titleView != null) { + titleView.setText(label); + } + final TextView breadcrumbView = (TextView) rootView.findViewById(R.id.lb_breadcrumb); + if (breadcrumbView != null) { + breadcrumbView.setText(R.string.app_permissions); + } + } + + @Override + public void onPermissionsLoaded() { + Context context = getActivity(); + PreferenceScreen preferences = getPreferenceScreen(); + if (preferences == null) { + preferences = getPreferenceManager().createPreferenceScreen(getActivity()); + setPreferenceScreen(preferences); + } + preferences.removeAll(); + for (PermissionApp app : mPermissionApps.getApps()) { + SwitchPreference pref = (SwitchPreference) findPreference(app.getKey()); + if (pref == null) { + pref = new SwitchPreference(context); + pref.setOnPreferenceChangeListener(this); + pref.setKey(app.getKey()); + pref.setIcon(app.getIcon()); + pref.setTitle(app.getLabel()); + pref.setPersistent(false); + preferences.addPreference(pref); + } + pref.setChecked(app.areRuntimePermissionsGranted()); + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String pkg = preference.getKey(); + PermissionApp app = mPermissionApps.getApp(pkg); + + if (app == null) { + return false; + } + if (newValue == Boolean.TRUE) { + app.grantRuntimePermissions(); + } else { + app.revokeRuntimePermissions(); + } + return true; + } + +} diff --git a/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java b/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java new file mode 100644 index 00000000..e1e3abe2 --- /dev/null +++ b/src/com/android/packageinstaller/permission/ui/SettingsWithHeader.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.packageinstaller.permission.ui; + +import android.content.Intent; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.preference.PreferenceFragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.packageinstaller.R; + +public abstract class SettingsWithHeader extends PreferenceFragment implements OnClickListener { + + private View mHeader; + private Intent mInfoIntent; + private Drawable mIcon; + private CharSequence mLabel; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + LinearLayout contentParent = + (LinearLayout) super.onCreateView(inflater, container, savedInstanceState); + mHeader = inflater.inflate(R.layout.header, contentParent, false); + contentParent.addView(mHeader, 0); + updateHeader(); + + return contentParent; + } + + public void setHeader(Drawable icon, CharSequence label, Intent infoIntent) { + mIcon = icon; + mLabel = label; + mInfoIntent = infoIntent; + updateHeader(); + } + + private void updateHeader() { + if (mHeader != null) { + final ImageView appIcon = (ImageView) mHeader.findViewById(R.id.icon); + appIcon.setImageDrawable(mIcon); + + final TextView appName = (TextView) mHeader.findViewById(R.id.name); + appName.setText(mLabel); + + final View info = mHeader.findViewById(R.id.info); + if (mInfoIntent == null) { + info.setVisibility(View.GONE); + } else { + info.setClickable(true); + info.setOnClickListener(this); + } + } + } + + @Override + public void onClick(View v) { + getActivity().startActivity(mInfoIntent); + } + +} |