From 20da6fde1f579e58ea83feafa8e7bd96f473fb05 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Thu, 14 May 2015 15:27:02 -0700 Subject: Add logging for user permission interactions. bug:21078221 Change-Id: Ie5bfb4c6013faf528b95eda0d5caf1c591f1e439 --- .../permission/model/Permission.java | 4 ++ .../permission/model/PermissionApps.java | 18 ++++-- .../permission/model/PermissionGroup.java | 10 +++ .../permission/ui/AppPermissionsFragment.java | 33 ++++++++++ .../permission/ui/GrantPermissionsActivity.java | 19 ++++++ .../permission/ui/PermissionAppsFragment.java | 40 ++++++++++++ .../permission/utils/SafetyNetLogger.java | 72 ++++++++++++++++++++++ 7 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java diff --git a/src/com/android/packageinstaller/permission/model/Permission.java b/src/com/android/packageinstaller/permission/model/Permission.java index 388ae75a..09c927be 100644 --- a/src/com/android/packageinstaller/permission/model/Permission.java +++ b/src/com/android/packageinstaller/permission/model/Permission.java @@ -44,6 +44,10 @@ public final class Permission { return mAppOp; } + public int getFlags() { + return mFlags; + } + public boolean hasAppOp() { return mAppOp != AppOpsManager.OP_NONE; } diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java index 81e5af51..d3d46cfa 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionApps.java +++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java @@ -106,12 +106,14 @@ public class PermissionApps { } public static class PermissionApp implements Comparable { + private final String mPackageName; private final PermissionGroup mPermissionGroup; private final String mLabel; private final Drawable mIcon; - public PermissionApp(PermissionGroup permissionGroup, String label, - Drawable icon) { + public PermissionApp(String packageName, PermissionGroup permissionGroup, + String label, Drawable icon) { + mPackageName = packageName; mPermissionGroup = permissionGroup; mLabel = label; mIcon = icon; @@ -149,6 +151,14 @@ public class PermissionApps { return mPermissionGroup.isSystemFixed(); } + public String getPackageName() { + return mPackageName; + } + + public PermissionGroup getPermissionGroup() { + return mPermissionGroup; + } + @Override public int compareTo(PermissionApp another) { final int result = mLabel.compareTo(another.mLabel); @@ -209,8 +219,8 @@ public class PermissionApps { PermissionGroup group = PermissionGroup.create(mContext, app, groupInfo, groupPermInfos); - PermissionApp permApp = new PermissionApp(group, - app.applicationInfo.loadLabel(mPm).toString(), + PermissionApp permApp = new PermissionApp(app.packageName, + group, app.applicationInfo.loadLabel(mPm).toString(), getBadgedIcon(app.applicationInfo)); permApps.add(permApp); diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroup.java b/src/com/android/packageinstaller/permission/model/PermissionGroup.java index 1f20e442..9e90d4ff 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionGroup.java +++ b/src/com/android/packageinstaller/permission/model/PermissionGroup.java @@ -402,6 +402,16 @@ public final class PermissionGroup implements Comparable { return new ArrayList<>(mPermissions.values()); } + public int getFlags() { + int flags = 0; + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + flags |= permission.getFlags(); + } + return flags; + } + public boolean isUserFixed() { final int permissionCount = mPermissions.size(); for (int i = 0; i < permissionCount; i++) { diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java index 7b64d7b3..a7c404cc 100644 --- a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java @@ -49,8 +49,12 @@ import android.widget.Toast; import com.android.packageinstaller.R; import com.android.packageinstaller.permission.model.AppPermissions; import com.android.packageinstaller.permission.model.PermissionGroup; +import com.android.packageinstaller.permission.utils.SafetyNetLogger; import com.android.packageinstaller.permission.utils.Utils; +import java.util.ArrayList; +import java.util.List; + public final class AppPermissionsFragment extends SettingsWithHeader implements OnPreferenceChangeListener { @@ -60,6 +64,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader private static final String EXTRA_HIDE_INFO_BUTTON = "hideInfoButton"; + private List mToggledGroups; private AppPermissions mAppPermissions; private PreferenceScreen mExtraScreen; @@ -222,6 +227,8 @@ public final class AppPermissionsFragment extends SettingsWithHeader return false; } + addToggledGroup(group); + if (newValue == Boolean.TRUE) { group.grantRuntimePermissions(false); } else { @@ -248,6 +255,32 @@ public final class AppPermissionsFragment extends SettingsWithHeader return true; } + @Override + public void onPause() { + super.onPause(); + logToggledGroups(); + } + + private void addToggledGroup(PermissionGroup group) { + if (mToggledGroups == null) { + mToggledGroups = new ArrayList<>(); + } + // Double toggle is back to initial state. + if (mToggledGroups.contains(group)) { + mToggledGroups.remove(group); + } else { + mToggledGroups.add(group); + } + } + + private void logToggledGroups() { + if (mToggledGroups != null) { + String packageName = mAppPermissions.getPackageInfo().packageName; + SafetyNetLogger.logPermissionsToggled(packageName, mToggledGroups); + mToggledGroups = null; + } + } + private void updateUi() { mAppPermissions.refresh(); diff --git a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java index 9ed47df9..b406db18 100644 --- a/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java +++ b/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java @@ -37,6 +37,10 @@ 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; +import com.android.packageinstaller.permission.utils.SafetyNetLogger; + +import java.util.ArrayList; +import java.util.List; public class GrantPermissionsActivity extends Activity implements GrantPermissionViewHandler.OnRequestGrantPermissionGroupResult { @@ -289,6 +293,7 @@ public class GrantPermissionsActivity extends Activity implements } private void setResultAndFinish() { + logRequestedPermissionGroups(); Intent result = new Intent(PackageManager.ACTION_REQUEST_PERMISSIONS); result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, mRequestedPermissions); result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, mGrantResults); @@ -296,6 +301,20 @@ public class GrantPermissionsActivity extends Activity implements finish(); } + private void logRequestedPermissionGroups() { + if (mRequestGrantPermissionGroups.isEmpty()) { + return; + } + + final int groupCount = mRequestGrantPermissionGroups.size(); + List groups = new ArrayList<>(groupCount); + for (int i = 0; i < groupCount; i++) { + groups.add(mRequestGrantPermissionGroups.valueAt(i).mGroup); + } + + SafetyNetLogger.logPermissionsRequested(mAppPermissions.getPackageInfo(), groups); + } + private static final class GroupState { public static final int STATE_UNKNOWN = 0; public static final int STATE_ALLOWED = 1; diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java index f18acfe3..dae90b93 100644 --- a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java @@ -25,6 +25,7 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; +import android.support.v4.util.ArrayMap; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -36,6 +37,11 @@ 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; +import com.android.packageinstaller.permission.model.PermissionGroup; +import com.android.packageinstaller.permission.utils.SafetyNetLogger; + +import java.util.ArrayList; +import java.util.List; public final class PermissionAppsFragment extends SettingsWithHeader implements Callback, OnPreferenceChangeListener { @@ -50,6 +56,8 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements private PermissionApps mPermissionApps; + private ArrayMap mToggledGroups; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -156,6 +164,8 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements String pkg = preference.getKey(); PermissionApp app = mPermissionApps.getApp(pkg); + addToggledGroup(app.getPackageName(), app.getPermissionGroup()); + if (app == null) { return false; } @@ -167,4 +177,34 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements return true; } + @Override + public void onPause() { + super.onPause(); + logToggledGroups(); + } + + private void addToggledGroup(String packageName, PermissionGroup group) { + if (mToggledGroups == null) { + mToggledGroups = new ArrayMap<>(); + } + // Double toggle is back to initial state. + if (mToggledGroups.containsKey(packageName)) { + mToggledGroups.remove(packageName); + } else { + mToggledGroups.put(packageName, group); + } + } + + private void logToggledGroups() { + if (mToggledGroups != null) { + final int groupCount = mToggledGroups.size(); + for (int i = 0; i < groupCount; i++) { + String packageName = mToggledGroups.keyAt(i); + List groups = new ArrayList<>(); + groups.add(mToggledGroups.valueAt(i)); + SafetyNetLogger.logPermissionsToggled(packageName, groups); + } + mToggledGroups = null; + } + } } diff --git a/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java b/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java new file mode 100644 index 00000000..0163b750 --- /dev/null +++ b/src/com/android/packageinstaller/permission/utils/SafetyNetLogger.java @@ -0,0 +1,72 @@ +/* + * 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.utils; + +import android.content.pm.PackageInfo; +import android.util.EventLog; +import com.android.packageinstaller.permission.model.PermissionGroup; + +import java.util.List; + +public final class SafetyNetLogger { + + // The log tag used by SafetyNet to pick entries from the event log. + private static final int SNET_NET_EVENT_LOG_TAG = 0x534e4554; + + // Log tag for the result of permissions request. + private static final String PERMISSIONS_REQUESTED = "permissions_requested"; + + // Log tag for the result of permissions toggling. + private static final String PERMISSIONS_TOGGLED = "permissions_toggled"; + + private SafetyNetLogger() { + /* do nothing */ + } + + public static void logPermissionsRequested(PackageInfo packageInfo, + List groups) { + EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_REQUESTED, + packageInfo.applicationInfo.uid, buildChangedGroupForPackageMessage( + packageInfo.packageName, groups)); + } + + public static void logPermissionsToggled(String packageName, List groups) { + EventLog.writeEvent(SNET_NET_EVENT_LOG_TAG, PERMISSIONS_TOGGLED, + android.os.Process.myUid(), buildChangedGroupForPackageMessage( + packageName, groups)); + } + + private static String buildChangedGroupForPackageMessage(String packageName, + List groups) { + StringBuilder builder = new StringBuilder(); + + builder.append(packageName).append(':'); + + final int groupCount = groups.size(); + for (int i = 0; i < groupCount; i++) { + PermissionGroup group = groups.get(i); + if (i > 0) { + builder.append(';'); + } + builder.append(group.getName()).append('|'); + builder.append(group.areRuntimePermissionsGranted()).append('|'); + builder.append(group.getFlags()); + } + + return builder.toString(); + } +} -- cgit v1.2.3 From 948d9f7a3a7224d18d209f024bbdb48a080da53c Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Thu, 14 May 2015 17:11:17 -0700 Subject: Fix truncated permission message if 'Do not ask again' is shown Change-Id: I4b1d3b815b6047937b89d4767583efe9bce3fab0 --- res/layout/grant_permissions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/layout/grant_permissions.xml b/res/layout/grant_permissions.xml index 2a5f7a93..93703053 100644 --- a/res/layout/grant_permissions.xml +++ b/res/layout/grant_permissions.xml @@ -39,7 +39,7 @@ Date: Thu, 14 May 2015 19:34:07 -0700 Subject: Don't show permission with no app ops. We have some permissions that we will be getting rid of and for that reason do not have app ops. Such permission were showing in the UI for legacy apps but changing them has no effect because there is no app ops support. We are not not showing them in the UI to avoid user frustration. bug:21168530 Change-Id: I2b6988f003e27b266fb2b48ddbb692ae5cf131fb --- .../permission/model/PermissionApps.java | 8 ++++++++ .../permission/model/PermissionGroup.java | 17 ++++++++++++++--- .../permission/ui/AppPermissionsFragment.java | 10 +++++++++- .../permission/ui/PermissionAppsFragment.java | 8 ++++++++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/com/android/packageinstaller/permission/model/PermissionApps.java b/src/com/android/packageinstaller/permission/model/PermissionApps.java index d3d46cfa..10ec9596 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionApps.java +++ b/src/com/android/packageinstaller/permission/model/PermissionApps.java @@ -151,6 +151,14 @@ public class PermissionApps { return mPermissionGroup.isSystemFixed(); } + public boolean hasRuntimePermissions() { + return mPermissionGroup.hasRuntimePermission(); + } + + public boolean hasAppOpPermissions() { + return mPermissionGroup.hasAppOpPermission(); + } + public String getPackageName() { return mPackageName; } diff --git a/src/com/android/packageinstaller/permission/model/PermissionGroup.java b/src/com/android/packageinstaller/permission/model/PermissionGroup.java index 9e90d4ff..901f1a4e 100644 --- a/src/com/android/packageinstaller/permission/model/PermissionGroup.java +++ b/src/com/android/packageinstaller/permission/model/PermissionGroup.java @@ -173,8 +173,19 @@ public final class PermissionGroup implements Comparable { : com.android.internal.R.drawable.ic_perm_device_info; } - public boolean isAppOpPermission() { - return !mAppSupportsRuntimePermissions; + public boolean hasRuntimePermission() { + return mAppSupportsRuntimePermissions; + } + + public boolean hasAppOpPermission() { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + Permission permission = mPermissions.valueAt(i); + if (permission.getAppOp() != AppOpsManager.OP_NONE) { + return true; + } + } + return false; } public PackageInfo getApp() { @@ -512,7 +523,7 @@ public final class PermissionGroup implements Comparable { return builder.toString(); } - void addPermission(Permission permission) { + private void addPermission(Permission permission) { mPermissions.put(permission.getName(), permission); } } diff --git a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java index a7c404cc..f0e8dba4 100644 --- a/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/AppPermissionsFragment.java @@ -180,6 +180,14 @@ public final class AppPermissionsFragment extends SettingsWithHeader if (group.isSystemFixed()) { continue; } + + // Yes this is possible. We have leftover permissions that + // are not in the final groups and we want to get rid of, + // therefore we do not have app ops for legacy support. + if (!group.hasRuntimePermission() && !group.hasAppOpPermission()) { + continue; + } + SwitchPreference preference = new SwitchPreference(activity); preference.setOnPreferenceChangeListener(this); preference.setKey(group.getName()); @@ -232,7 +240,7 @@ public final class AppPermissionsFragment extends SettingsWithHeader if (newValue == Boolean.TRUE) { group.grantRuntimePermissions(false); } else { - if (group.isAppOpPermission() && !mHasConfirmedRevoke) { + if (group.hasAppOpPermission() && !mHasConfirmedRevoke) { new AlertDialog.Builder(getContext()) .setMessage(R.string.old_sdk_deny_warning) .setNegativeButton(R.string.cancel, null) diff --git a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java index dae90b93..b8ae369d 100644 --- a/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java +++ b/src/com/android/packageinstaller/permission/ui/PermissionAppsFragment.java @@ -144,6 +144,14 @@ public final class PermissionAppsFragment extends SettingsWithHeader implements if (app.isSystemFixed()) { continue; } + + // Yes this is possible. We have leftover permissions that + // are not in the final groups and we want to get rid of, + // therefore we do not have app ops for legacy support. + if (!app.hasRuntimePermissions() && !app.hasAppOpPermissions()) { + continue; + } + SwitchPreference pref = (SwitchPreference) findPreference(app.getKey()); if (pref == null) { pref = new SwitchPreference(context); -- cgit v1.2.3 From 0dec9efe6d445d65a40d392638c13f510e3f6520 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Wed, 8 Jul 2015 13:03:17 -0700 Subject: Make package installer a privileged core app Package installer should be a core app, so it is available when we boot in a core app only mode for the user to enter a pattern to decrypt. Package installer is now a privileged app as it needs provileged permissions in the additions to the ones we explicitly grant it. This is to ensure it will get these permissions when its cert changes. bug:22341030 Change-Id: I52137fe181b84fca6d49fb6b1b363527f0fd323c --- Android.mk | 2 ++ AndroidManifest.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index d46c7f33..5a53086e 100644 --- a/Android.mk +++ b/Android.mk @@ -31,6 +31,8 @@ LOCAL_AAPT_FLAGS := --auto-add-overlay \ LOCAL_PACKAGE_NAME := PackageInstaller LOCAL_CERTIFICATE := platform +LOCAL_PRIVILEGED_MODULE := true + LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index bcf59250..d0c106c6 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="com.android.packageinstaller" coreApp="true"> -- cgit v1.2.3