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

Commit 8d76e722 authored by Bartosz Fabianowski's avatar Bartosz Fabianowski
Browse files

Allow DO to access bookkeeping information about its own actions

The getLastSecurityLogRetrievalTime(), getLastBugReportRequestTime()
and getLastNetworkLogRetrievalTime() methods are meant to be used by
system code. However, there is no harm in allowing the DO to access the
information they return - because it is information about actions that
the DO itself took.

The advantage of opening up these methods to the DO is that we can
CTS-test them.

Bug: 32692748
Test: DevicePolicyManager unit test + CTS test in separate CL

Change-Id: I1470fca2a82b9955f7aed5e8b50220bea8b56fc9
parent 2dd5018a
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -6034,6 +6034,9 @@ package android.app.admin {
    method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
    method public java.lang.CharSequence getDeviceOwnerLockScreenInfo();
    method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
    method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName);
    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
    method public int getKeyguardDisabledFeatures(android.content.ComponentName);
    method public long getLastBugReportRequestTime();
    method public long getLastNetworkLogRetrievalTime();
    method public long getLastSecurityLogRetrievalTime();
    method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
    method public java.lang.CharSequence getLongSupportMessage(android.content.ComponentName);
    method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
    method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
    method public long getMaximumTimeToLock(android.content.ComponentName);
    method public long getMaximumTimeToLock(android.content.ComponentName);
+10 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.annotation.WorkerThread;
import android.app.Activity;
import android.app.Activity;
@@ -6784,9 +6785,12 @@ public class DevicePolicyManager {
     *
     *
     * @return the time at which the device owner most recently retrieved security logging entries,
     * @return the time at which the device owner most recently retrieved security logging entries,
     *         in milliseconds since epoch; -1 if security logging entries were never retrieved.
     *         in milliseconds since epoch; -1 if security logging entries were never retrieved.
     * @throws SecurityException if the caller is not the device owner, does not hold the
     *         MANAGE_USERS permission and is not the system.
     *
     *
     * @hide
     * @hide
     */
     */
    @TestApi
    public long getLastSecurityLogRetrievalTime() {
    public long getLastSecurityLogRetrievalTime() {
        try {
        try {
            return mService.getLastSecurityLogRetrievalTime();
            return mService.getLastSecurityLogRetrievalTime();
@@ -6800,9 +6804,12 @@ public class DevicePolicyManager {
     *
     *
     * @return the time at which the device owner most recently requested a bug report, in
     * @return the time at which the device owner most recently requested a bug report, in
     *         milliseconds since epoch; -1 if a bug report was never requested.
     *         milliseconds since epoch; -1 if a bug report was never requested.
     * @throws SecurityException if the caller is not the device owner, does not hold the
     *         MANAGE_USERS permission and is not the system.
     *
     *
     * @hide
     * @hide
     */
     */
    @TestApi
    public long getLastBugReportRequestTime() {
    public long getLastBugReportRequestTime() {
        try {
        try {
            return mService.getLastBugReportRequestTime();
            return mService.getLastBugReportRequestTime();
@@ -6817,9 +6824,12 @@ public class DevicePolicyManager {
     *
     *
     * @return the time at which the device owner most recently retrieved network logging events, in
     * @return the time at which the device owner most recently retrieved network logging events, in
     *         milliseconds since epoch; -1 if network logging events were never retrieved.
     *         milliseconds since epoch; -1 if network logging events were never retrieved.
     * @throws SecurityException if the caller is not the device owner, does not hold the
     *         MANAGE_USERS permission and is not the system.
     *
     *
     * @hide
     * @hide
     */
     */
    @TestApi
    public long getLastNetworkLogRetrievalTime() {
    public long getLastNetworkLogRetrievalTime() {
        try {
        try {
            return mService.getLastNetworkLogRetrievalTime();
            return mService.getLastNetworkLogRetrievalTime();
+15 −6
Original line number Original line Diff line number Diff line
@@ -6097,6 +6097,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            admin.userRestrictions = null;
            admin.userRestrictions = null;
            admin.forceEphemeralUsers = false;
            admin.forceEphemeralUsers = false;
            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
            mUserManagerInternal.setForceEphemeralUsers(admin.forceEphemeralUsers);
            final DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
            policyData.mLastSecurityLogRetrievalTime = -1;
            policyData.mLastBugReportRequestTime = -1;
            policyData.mLastNetworkLogsRetrievalTime = -1;
            saveSettingsLocked(UserHandle.USER_SYSTEM);
        }
        }
        clearUserPoliciesLocked(userId);
        clearUserPoliciesLocked(userId);


@@ -6581,10 +6586,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }
    }
    }


    private void enforceSystemUid() {
    private void enforceDeviceOwnerOrManageUsers() {
        if (!isCallerWithSystemUid()) {
        synchronized (this) {
            throw new SecurityException("Only the system can call this method.");
            if (getActiveAdminWithPolicyForUidLocked(null, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER,
                    mInjector.binderGetCallingUid()) != null) {
                return;
            }
        }
        }
        enforceManageUsers();
    }
    }


    private void ensureCallerPackage(@Nullable String packageName) {
    private void ensureCallerPackage(@Nullable String packageName) {
@@ -9852,19 +9861,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {


    @Override
    @Override
    public long getLastSecurityLogRetrievalTime() {
    public long getLastSecurityLogRetrievalTime() {
        enforceSystemUid();
        enforceDeviceOwnerOrManageUsers();
        return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime;
        return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime;
     }
     }


    @Override
    @Override
    public long getLastBugReportRequestTime() {
    public long getLastBugReportRequestTime() {
        enforceSystemUid();
        enforceDeviceOwnerOrManageUsers();
        return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime;
        return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime;
     }
     }


    @Override
    @Override
    public long getLastNetworkLogRetrievalTime() {
    public long getLastNetworkLogRetrievalTime() {
        enforceSystemUid();
        enforceDeviceOwnerOrManageUsers();
        return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime;
        return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime;
    }
    }
}
}
+65 −35
Original line number Original line Diff line number Diff line
@@ -2273,11 +2273,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        assertFalse(dpms.hasUserSetupCompleted());
        assertFalse(dpms.hasUserSetupCompleted());
    }
    }


    private long getLastSecurityLogRetrievalTime() {
    private void clearDeviceOwner() throws Exception {
        final long ident = mContext.binder.clearCallingIdentity();
        final long ident = mContext.binder.clearCallingIdentity();
        final long lastSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
        doReturn(DpmMockContext.CALLER_SYSTEM_USER_UID).when(mContext.packageManager)
                .getPackageUidAsUser(eq(admin1.getPackageName()), anyInt());
        dpm.clearDeviceOwnerApp(admin1.getPackageName());
        mContext.binder.restoreCallingIdentity(ident);
        mContext.binder.restoreCallingIdentity(ident);
        return lastSecurityLogRetrievalTime;
    }
    }


    public void testGetLastSecurityLogRetrievalTime() throws Exception {
    public void testGetLastSecurityLogRetrievalTime() throws Exception {
@@ -2288,16 +2290,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                .thenReturn(true);
                .thenReturn(true);


        // No logs were retrieved so far.
        // No logs were retrieved so far.
        assertEquals(-1, getLastSecurityLogRetrievalTime());
        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());


        // Enabling logging should not change the timestamp.
        // Enabling logging should not change the timestamp.
        dpm.setSecurityLoggingEnabled(admin1, true);
        dpm.setSecurityLoggingEnabled(admin1, true);
        assertEquals(-1, getLastSecurityLogRetrievalTime());
        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());


        // Retrieving the logs should update the timestamp.
        // Retrieving the logs should update the timestamp.
        final long beforeRetrieval = System.currentTimeMillis();
        final long beforeRetrieval = System.currentTimeMillis();
        dpm.retrieveSecurityLogs(admin1);
        dpm.retrieveSecurityLogs(admin1);
        final long firstSecurityLogRetrievalTime = getLastSecurityLogRetrievalTime();
        final long firstSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
        final long afterRetrieval = System.currentTimeMillis();
        final long afterRetrieval = System.currentTimeMillis();
        assertTrue(firstSecurityLogRetrievalTime >= beforeRetrieval);
        assertTrue(firstSecurityLogRetrievalTime >= beforeRetrieval);
        assertTrue(firstSecurityLogRetrievalTime <= afterRetrieval);
        assertTrue(firstSecurityLogRetrievalTime <= afterRetrieval);
@@ -2305,33 +2307,40 @@ public class DevicePolicyManagerTest extends DpmTestBase {
        // Retrieving the pre-boot logs should update the timestamp.
        // Retrieving the pre-boot logs should update the timestamp.
        Thread.sleep(2);
        Thread.sleep(2);
        dpm.retrievePreRebootSecurityLogs(admin1);
        dpm.retrievePreRebootSecurityLogs(admin1);
        final long secondSecurityLogRetrievalTime = getLastSecurityLogRetrievalTime();
        final long secondSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
        assertTrue(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime);
        assertTrue(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime);


        // Checking the timestamp again should not change it.
        // Checking the timestamp again should not change it.
        Thread.sleep(2);
        Thread.sleep(2);
        assertEquals(secondSecurityLogRetrievalTime, getLastSecurityLogRetrievalTime());
        assertEquals(secondSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());


        // Retrieving the logs again should update the timestamp.
        // Retrieving the logs again should update the timestamp.
        dpm.retrieveSecurityLogs(admin1);
        dpm.retrieveSecurityLogs(admin1);
        final long thirdSecurityLogRetrievalTime = getLastSecurityLogRetrievalTime();
        final long thirdSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
        assertTrue(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime);
        assertTrue(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime);


        // Disabling logging should not change the timestamp.
        // Disabling logging should not change the timestamp.
        Thread.sleep(2);
        Thread.sleep(2);
        dpm.setSecurityLoggingEnabled(admin1, false);
        dpm.setSecurityLoggingEnabled(admin1, false);
        assertEquals(thirdSecurityLogRetrievalTime, getLastSecurityLogRetrievalTime());
        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());


        // Restarting the DPMS should not lose the timestamp.
        // Restarting the DPMS should not lose the timestamp.
        initializeDpms();
        initializeDpms();
        assertEquals(thirdSecurityLogRetrievalTime, getLastSecurityLogRetrievalTime());
        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
    }


    private long getLastBugReportRequestTime() {
        // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
        final long ident = mContext.binder.clearCallingIdentity();
        mContext.binder.callingUid = 1234567;
        final long lastBugRequestTime = dpm.getLastBugReportRequestTime();
        mContext.callerPermissions.add(permission.MANAGE_USERS);
        mContext.binder.restoreCallingIdentity(ident);
        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
        return lastBugRequestTime;
        mContext.callerPermissions.remove(permission.MANAGE_USERS);

        // System can retrieve the timestamp.
        mContext.binder.clearCallingIdentity();
        assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());

        // Removing the device owner should clear the timestamp.
        clearDeviceOwner();
        assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
    }
    }


    public void testGetLastBugReportRequestTime() throws Exception {
    public void testGetLastBugReportRequestTime() throws Exception {
@@ -2346,30 +2355,37 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                anyObject())).thenReturn(Color.WHITE);
                anyObject())).thenReturn(Color.WHITE);


        // No bug reports were requested so far.
        // No bug reports were requested so far.
        assertEquals(-1, getLastSecurityLogRetrievalTime());
        assertEquals(-1, dpm.getLastBugReportRequestTime());


        // Requesting a bug report should update the timestamp.
        // Requesting a bug report should update the timestamp.
        final long beforeRequest = System.currentTimeMillis();
        final long beforeRequest = System.currentTimeMillis();
        dpm.requestBugreport(admin1);
        dpm.requestBugreport(admin1);
        final long bugReportRequestTime = getLastBugReportRequestTime();
        final long bugReportRequestTime = dpm.getLastBugReportRequestTime();
        final long afterRequest = System.currentTimeMillis();
        final long afterRequest = System.currentTimeMillis();
        assertTrue(bugReportRequestTime >= beforeRequest);
        assertTrue(bugReportRequestTime >= beforeRequest);
        assertTrue(bugReportRequestTime <= afterRequest);
        assertTrue(bugReportRequestTime <= afterRequest);


        // Checking the timestamp again should not change it.
        // Checking the timestamp again should not change it.
        Thread.sleep(2);
        Thread.sleep(2);
        assertEquals(bugReportRequestTime, getLastBugReportRequestTime());
        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());


        // Restarting the DPMS should not lose the timestamp.
        // Restarting the DPMS should not lose the timestamp.
        initializeDpms();
        initializeDpms();
        assertEquals(bugReportRequestTime, getLastBugReportRequestTime());
        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
    }


    private long getLastNetworkLogRetrievalTime() {
        // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
        final long ident = mContext.binder.clearCallingIdentity();
        mContext.binder.callingUid = 1234567;
        final long lastNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
        mContext.callerPermissions.add(permission.MANAGE_USERS);
        mContext.binder.restoreCallingIdentity(ident);
        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
        return lastNetworkLogRetrievalTime;
        mContext.callerPermissions.remove(permission.MANAGE_USERS);

        // System can retrieve the timestamp.
        mContext.binder.clearCallingIdentity();
        assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());

        // Removing the device owner should clear the timestamp.
        clearDeviceOwner();
        assertEquals(-1, dpm.getLastBugReportRequestTime());
    }
    }


    public void testGetLastNetworkLogRetrievalTime() throws Exception {
    public void testGetLastNetworkLogRetrievalTime() throws Exception {
@@ -2380,41 +2396,55 @@ public class DevicePolicyManagerTest extends DpmTestBase {
                .thenReturn(true);
                .thenReturn(true);


        // No logs were retrieved so far.
        // No logs were retrieved so far.
        assertEquals(-1, getLastNetworkLogRetrievalTime());
        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());


        // Attempting to retrieve logs without enabling logging should not change the timestamp.
        // Attempting to retrieve logs without enabling logging should not change the timestamp.
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        assertEquals(-1, getLastNetworkLogRetrievalTime());
        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());


        // Enabling logging should not change the timestamp.
        // Enabling logging should not change the timestamp.
        dpm.setNetworkLoggingEnabled(admin1, true);
        dpm.setNetworkLoggingEnabled(admin1, true);
        assertEquals(-1, getLastNetworkLogRetrievalTime());
        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());


        // Retrieving the logs should update the timestamp.
        // Retrieving the logs should update the timestamp.
        final long beforeRetrieval = System.currentTimeMillis();
        final long beforeRetrieval = System.currentTimeMillis();
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        final long firstNetworkLogRetrievalTime = getLastNetworkLogRetrievalTime();
        final long firstNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
        final long afterRetrieval = System.currentTimeMillis();
        final long afterRetrieval = System.currentTimeMillis();
        assertTrue(firstNetworkLogRetrievalTime >= beforeRetrieval);
        assertTrue(firstNetworkLogRetrievalTime >= beforeRetrieval);
        assertTrue(firstNetworkLogRetrievalTime <= afterRetrieval);
        assertTrue(firstNetworkLogRetrievalTime <= afterRetrieval);


        // Checking the timestamp again should not change it.
        // Checking the timestamp again should not change it.
        Thread.sleep(2);
        Thread.sleep(2);
        assertEquals(firstNetworkLogRetrievalTime, getLastNetworkLogRetrievalTime());
        assertEquals(firstNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());


        // Retrieving the logs again should update the timestamp.
        // Retrieving the logs again should update the timestamp.
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
        final long secondNetworkLogRetrievalTime = getLastNetworkLogRetrievalTime();
        final long secondNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
        assertTrue(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime);
        assertTrue(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime);


        // Disabling logging should not change the timestamp.
        // Disabling logging should not change the timestamp.
        Thread.sleep(2);
        Thread.sleep(2);
        dpm.setNetworkLoggingEnabled(admin1, false);
        dpm.setNetworkLoggingEnabled(admin1, false);
        assertEquals(secondNetworkLogRetrievalTime, getLastNetworkLogRetrievalTime());
        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());


        // Restarting the DPMS should not lose the timestamp.
        // Restarting the DPMS should not lose the timestamp.
        initializeDpms();
        initializeDpms();
        assertEquals(secondNetworkLogRetrievalTime, getLastNetworkLogRetrievalTime());
        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());

        // Any uid holding MANAGE_USERS permission can retrieve the timestamp.
        mContext.binder.callingUid = 1234567;
        mContext.callerPermissions.add(permission.MANAGE_USERS);
        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
        mContext.callerPermissions.remove(permission.MANAGE_USERS);

        // System can retrieve the timestamp.
        mContext.binder.clearCallingIdentity();
        assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());

        // Removing the device owner should clear the timestamp.
        clearDeviceOwner();
        assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
    }
    }


    private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {
    private void setUserSetupCompleteForUser(boolean isUserSetupComplete, int userhandle) {