Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1ad710b1 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Android (Google) Code Review
Browse files

Merge "Log individual permission grants, denials via TRON"

parents d2f59ad7 475856df
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ LOCAL_STATIC_ANDROID_LIBRARIES += \
    SettingsLib

LOCAL_STATIC_JAVA_LIBRARIES := \
    framework-protos \
    xz-java

LOCAL_PACKAGE_NAME := PackageInstaller
@@ -33,3 +34,10 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags
# LOCAL_SDK_VERSION := system_current

include $(BUILD_PACKAGE)

ifeq (PackageInstaller,$(LOCAL_PACKAGE_NAME))
# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
include $(call all-makefiles-under,$(LOCAL_PATH))
endif
endif
+19 −1
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.packageinstaller.permission.ui;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import android.Manifest;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -49,6 +48,7 @@ import com.android.packageinstaller.permission.model.Permission;
import com.android.packageinstaller.permission.ui.auto.GrantPermissionsAutoViewHandler;
import com.android.packageinstaller.permission.ui.handheld.GrantPermissionsViewHandlerImpl;
import com.android.packageinstaller.permission.utils.ArrayUtils;
import com.android.packageinstaller.permission.utils.EventLogger;
import com.android.packageinstaller.permission.utils.SafetyNetLogger;

import java.util.ArrayList;
@@ -211,6 +211,14 @@ public class GrantPermissionsActivity extends OverlayTouchActivity

        if (!showNextPermissionGroupGrantRequest()) {
            setResultAndFinish();
        } else if (icicle == null) {
            int numRequestedPermissions = mRequestedPermissions.length;
            for (int permissionNum = 0; permissionNum < numRequestedPermissions; permissionNum++) {
                String permission = mRequestedPermissions[permissionNum];

                EventLogger.logPermissionRequested(this, permission,
                        mAppPermissions.getPackageInfo().packageName);
            }
        }
    }

@@ -301,6 +309,16 @@ public class GrantPermissionsActivity extends OverlayTouchActivity
                groupState.mGroup.revokeRuntimePermissions(doNotAskAgain,
                        groupState.affectedPermissions);
                groupState.mState = GroupState.STATE_DENIED;

                int numRequestedPermissions = mRequestedPermissions.length;
                for (int i = 0; i < numRequestedPermissions; i++) {
                    String permission = mRequestedPermissions[i];

                    if (groupState.mGroup.hasPermission(permission)) {
                        EventLogger.logPermissionDenied(this, permission,
                                mAppPermissions.getPackageInfo().packageName);
                    }
                }
            }
            updateGrantResults(groupState.mGroup);
        }
+128 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.Manifest;
import android.app.AppOpsManager;
import android.content.Context;
import android.os.SystemProperties;
import android.support.annotation.NonNull;
import android.util.Log;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

import java.util.Arrays;
import java.util.List;

/**
 * For each permission there are four events. The events are in the order of
 * #ALL_DANGEROUS_PERMISSIONS. The four events per permission are (in that order): "requested",
 * "granted", "denied", and "revoked".
 */
public class EventLogger {
    private static final String LOG_TAG = EventLogger.class.getSimpleName();

    /** All dangerous permission names in the same order as the events in MetricsEvent */
    private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
            Manifest.permission.READ_CALENDAR,
            Manifest.permission.WRITE_CALENDAR,
            Manifest.permission.CAMERA,
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.WRITE_CONTACTS,
            Manifest.permission.GET_ACCOUNTS,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.CALL_PHONE,
            Manifest.permission.READ_CALL_LOG,
            Manifest.permission.WRITE_CALL_LOG,
            Manifest.permission.ADD_VOICEMAIL,
            Manifest.permission.USE_SIP,
            Manifest.permission.PROCESS_OUTGOING_CALLS,
            Manifest.permission.READ_CELL_BROADCASTS,
            Manifest.permission.BODY_SENSORS,
            Manifest.permission.SEND_SMS,
            Manifest.permission.RECEIVE_SMS,
            Manifest.permission.READ_SMS,
            Manifest.permission.RECEIVE_WAP_PUSH,
            Manifest.permission.RECEIVE_MMS,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE);

    /**
     * Get the first event id for the permission.
     *
     * <p>There are four events for each permission: <ul>
     *     <li>Request permission: first id + 0</li>
     *     <li>Grant permission: first id + 1</li>
     *     <li>Request for permission denied: first id + 2</li>
     *     <li>Revoke permission: first id + 3</li>
     * </ul></p>
     *
     * @param name name of the permission
     *
     * @return The first event id for the permission
     */
    private static int getBaseEventId(@NonNull String name) {
        int eventIdIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name);

        if (eventIdIndex == -1) {
            if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE
                    || "user".equals(SystemProperties.get("ro.build.type"))) {
                Log.i(LOG_TAG, "Unknown permission " + name);

                return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN;
            } else {
                // Most likely #ALL_DANGEROUS_PERMISSIONS needs to be updated.
                //
                // Also update
                // - PackageManagerService#ALL_DANGEROUS_PERMISSIONS
                // - metrics_constants.proto
                throw new IllegalStateException("Unknown permission " + name);
            }
        }

        return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + eventIdIndex * 4;
    }

    /**
     * Log that a permission was requested.
     *
     * @param context Context of the caller
     * @param name name of the permission
     * @param packageName package permission if for
     */
    public static void logPermissionRequested(@NonNull Context context, @NonNull String name,
            @NonNull String packageName) {
        MetricsLogger.action(context, getBaseEventId(name), packageName);
    }

    /**
     * Log that a permission request was denied.
     *
     * @param context Context of the caller
     * @param name name of the permission
     * @param packageName package permission if for
     */
    public static void logPermissionDenied(@NonNull Context context, @NonNull String name,
            @NonNull String packageName) {
        MetricsLogger.action(context, getBaseEventId(name) + 2, packageName);
    }

}

tests/Android.mk

0 → 100644
+40 −0
Original line number Diff line number Diff line
#############################################
# PackageInstaller Robolectric test target. #
#############################################
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := $(call all-java-files-under, src)

# Include the testing libraries (JUnit4 + Robolectric libs).
LOCAL_STATIC_JAVA_LIBRARIES := \
    platform-system-robolectric

LOCAL_JAVA_LIBRARIES := \
    junit4-target \
    platform-robolectric-prebuilt

LOCAL_INSTRUMENTATION_FOR := PackageInstaller
LOCAL_MODULE := PackageInstallerRoboTests

LOCAL_MODULE_TAGS := optional

include $(BUILD_STATIC_JAVA_LIBRARY)

#############################################################
# PackageInstaller runner target to run the previous target. #
#############################################################
include $(CLEAR_VARS)

LOCAL_MODULE := RunPackageInstallerRoboTests

LOCAL_SDK_VERSION := current

LOCAL_STATIC_JAVA_LIBRARIES := \
    PackageInstallerRoboTests

LOCAL_TEST_PACKAGE := PackageInstaller

LOCAL_ROBOTEST_FAILURE_FATAL := true

include prebuilts/misc/common/robolectric/run_robotests.mk
+116 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import android.Manifest;

import com.android.internal.logging.nano.MetricsProto;
import com.android.packageinstaller.shadows.ShadowMetricsLogger;
import com.android.packageinstaller.shadows.ShadowSystemProperties;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

/**
 * Tests {@link com.android.packageinstaller.permission.utils.EventLogger}
 */
@RunWith(RobolectricTestRunner.class)
@Config(manifest = "packages/apps/PackageInstaller/AndroidManifest.xml",
        shadows = {ShadowMetricsLogger.class, ShadowSystemProperties.class},
        sdk = 23)
public class EventLoggerTest {
    @Before
    public void setUp() {
        ShadowSystemProperties.setUserBuild(true);
        ShadowMetricsLogger.clearLogs();
    }

    @Test
    public void testValidRequested() {
        EventLogger.logPermissionRequested(null, Manifest.permission.READ_CALENDAR,
                "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR,
                        "testPackage")));
    }

    @Test
    public void testValidDenied() {
        EventLogger.logPermissionDenied(null, Manifest.permission.READ_CALENDAR, "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + 2,
                        "testPackage")));
    }

    @Test
    public void testInvalidRequestedEngBuild() throws Throwable {
        ShadowSystemProperties.setUserBuild(false);
        EventLogger.logPermissionRequested(null, "invalid", "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN,
                        "testPackage")));
    }

    @Test
    public void testInvalidDeniedEngBuild() throws Throwable {
        ShadowSystemProperties.setUserBuild(false);
        EventLogger.logPermissionRequested(null, "invalid", "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN,
                        "testPackage")));
    }

    @Test
    public void testInvalidRequestedUserBuild() throws Throwable {
        EventLogger.logPermissionRequested(null, "invalid", "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN,
                        "testPackage")));
    }

    @Test
    public void testInvalidDeniedUserBuild() throws Throwable {
        EventLogger.logPermissionDenied(null, "invalid", "testPackage");

        assertEquals(1, ShadowMetricsLogger.getLogs().size());
        assertTrue(ShadowMetricsLogger.getLogs().contains(
                new ShadowMetricsLogger.Log(null,
                        MetricsProto.MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN + 2,
                        "testPackage")));
    }
}
Loading