OSDN Git Service

Add setTime and setTimeZone API.
authoryuemingw <yuemingw@google.com>
Thu, 12 Oct 2017 15:52:11 +0000 (16:52 +0100)
committeryuemingw <yuemingw@google.com>
Mon, 23 Oct 2017 09:53:15 +0000 (10:53 +0100)
Fix: 67497358
Test: wait for cts test in the following cl. For unitest:
 runtest -x services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java

Add setTime and setTimeZone API in devicepolicymanager.
Add unitest for each API.
Following design doc: https://docs.google.com/document/d/1NV93mr2CT157S_haru1QbKo9HLeP9iPM9eMiGfVmfCM/edit

Change-Id: I188c27b0b99137b6f01e42ae1ad49356ce0a81b2

api/current.txt
api/system-current.txt
api/test-current.txt
core/java/android/app/admin/DevicePolicyManager.java
core/java/android/app/admin/IDevicePolicyManager.aidl
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java

index 93cc843..0530744 100644 (file)
@@ -6445,6 +6445,8 @@ package android.app.admin {
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
+    method public boolean setTime(android.content.ComponentName, long);
+    method public boolean setTimeZone(android.content.ComponentName, java.lang.String);
     method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
     method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
index 9767e44..cfb7f9d 100644 (file)
@@ -6680,6 +6680,8 @@ package android.app.admin {
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
+    method public boolean setTime(android.content.ComponentName, long);
+    method public boolean setTimeZone(android.content.ComponentName, java.lang.String);
     method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
     method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
index 702ec3b..2546bbe 100644 (file)
@@ -6511,6 +6511,8 @@ package android.app.admin {
     method public boolean setStatusBarDisabled(android.content.ComponentName, boolean);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void setSystemUpdatePolicy(android.content.ComponentName, android.app.admin.SystemUpdatePolicy);
+    method public boolean setTime(android.content.ComponentName, long);
+    method public boolean setTimeZone(android.content.ComponentName, java.lang.String);
     method public void setTrustAgentConfiguration(android.content.ComponentName, android.content.ComponentName, android.os.PersistableBundle);
     method public void setUninstallBlocked(android.content.ComponentName, java.lang.String, boolean);
     method public void setUserIcon(android.content.ComponentName, android.graphics.Bitmap);
index 3c53063..ab8edee 100644 (file)
@@ -6533,6 +6533,52 @@ public class DevicePolicyManager {
     }
 
     /**
+     * Called by device owner to set the system wall clock time. This only takes effect if called
+     * when {@link android.provider.Settings.Global#AUTO_TIME} is 0, otherwise {@code false} will be
+     * returned.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param millis time in milliseconds since the Epoch
+     * @return {@code true} if set time succeeded, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public boolean setTime(@NonNull ComponentName admin, long millis) {
+        throwIfParentInstance("setTime");
+        if (mService != null) {
+            try {
+                return mService.setTime(admin, millis);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Called by device owner to set the system's persistent default time zone. This only takes
+     * effect if called when {@link android.provider.Settings.Global#AUTO_TIME_ZONE} is 0, otherwise
+     * {@code false} will be returned.
+     *
+     * @see android.app.AlarmManager#setTimeZone(String)
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with
+     * @param timeZone one of the Olson ids from the list returned by
+     *     {@link java.util.TimeZone#getAvailableIDs}
+     * @return {@code true} if set timezone succeeded, {@code false} otherwise.
+     * @throws SecurityException if {@code admin} is not a device owner.
+     */
+    public boolean setTimeZone(@NonNull ComponentName admin, String timeZone) {
+        throwIfParentInstance("setTimeZone");
+        if (mService != null) {
+            try {
+                return mService.setTimeZone(admin, timeZone);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by profile or device owners to update {@link android.provider.Settings.Secure}
      * settings. Validation that the value of the setting is in the correct form for the setting
      * type should be performed by the caller.
index 8865a05..e77c186 100644 (file)
@@ -229,6 +229,9 @@ interface IDevicePolicyManager {
     void setGlobalSetting(in ComponentName who, in String setting, in String value);
     void setSecureSetting(in ComponentName who, in String setting, in String value);
 
+    boolean setTime(in ComponentName who, long millis);
+    boolean setTimeZone(in ComponentName who, String timeZone);
+
     void setMasterVolumeMuted(in ComponentName admin, boolean on);
     boolean isMasterVolumeMuted(in ComponentName admin);
 
index c59f44e..80f6a4b 100644 (file)
@@ -175,6 +175,7 @@ import com.android.internal.os.BackgroundThread;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
@@ -1682,6 +1683,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
             return getCallingUid() == Process.myUid();
         }
 
+        void binderWithCleanCallingIdentity(@NonNull ThrowingRunnable action) {
+             Binder.withCleanCallingIdentity(action);
+        }
+
         final int userHandleGetCallingUserId() {
             return UserHandle.getUserId(binderGetCallingUid());
         }
@@ -9023,6 +9028,31 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     }
 
     @Override
+    public boolean setTime(ComponentName who, long millis) {
+        Preconditions.checkNotNull(who, "ComponentName is null in setTime");
+        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        // Don't allow set time when auto time is on.
+        if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) == 1) {
+            return false;
+        }
+        mInjector.binderWithCleanCallingIdentity(() -> mInjector.getAlarmManager().setTime(millis));
+        return true;
+    }
+
+    @Override
+    public boolean setTimeZone(ComponentName who, String timeZone) {
+        Preconditions.checkNotNull(who, "ComponentName is null in setTimeZone");
+        getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+        // Don't allow set timezone when auto timezone is on.
+        if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) {
+            return false;
+        }
+        mInjector.binderWithCleanCallingIdentity(() ->
+            mInjector.getAlarmManager().setTimeZone(timeZone));
+        return true;
+    }
+
+    @Override
     public void setSecureSetting(ComponentName who, String setting, String value) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         int callingUserId = mInjector.userHandleGetCallingUserId();
index 5471715..ae4b569 100644 (file)
@@ -15,6 +15,7 @@
  */
 package com.android.server.devicepolicy;
 
+import android.app.AlarmManager;
 import android.app.IActivityManager;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -34,11 +35,13 @@ import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.security.KeyChain;
+import android.support.annotation.NonNull;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.Pair;
 import android.view.IWindowManager;
 
+import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.widget.LockPatternUtils;
 
 import java.io.File;
@@ -194,6 +197,9 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
         }
 
         @Override
+        AlarmManager getAlarmManager() {return services.alarmManager;}
+
+        @Override
         LockPatternUtils newLockPatternUtils() {
             return services.lockPatternUtils;
         }
@@ -234,6 +240,11 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi
         }
 
         @Override
+        void binderWithCleanCallingIdentity(@NonNull ThrowingRunnable action) {
+            context.binder.withCleanCallingIdentity(action);
+        }
+
+        @Override
         int binderGetCallingUid() {
             return context.binder.getCallingUid();
         }
index a8bf8f1..e1e9cf5 100644 (file)
@@ -3090,6 +3090,47 @@ public class DevicePolicyManagerTest extends DpmTestBase {
         assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
     }
 
+    public void testSetTime() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        dpm.setTime(admin1, 0);
+        verify(getServices().alarmManager).setTime(0);
+    }
+
+    public void testSetTimeFailWithPO() throws Exception {
+        setupProfileOwner();
+        assertExpectException(SecurityException.class, null, () -> dpm.setTime(admin1, 0));
+    }
+
+    public void testSetTimeWithAutoTimeOn() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME, 0))
+                .thenReturn(1);
+        assertFalse(dpm.setTime(admin1, 0));
+    }
+
+    public void testSetTimeZone() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        dpm.setTimeZone(admin1, "Asia/Shanghai");
+        verify(getServices().alarmManager).setTimeZone("Asia/Shanghai");
+    }
+
+    public void testSetTimeZoneFailWithPO() throws Exception {
+        setupProfileOwner();
+        assertExpectException(SecurityException.class, null,
+                () -> dpm.setTimeZone(admin1, "Asia/Shanghai"));
+    }
+
+    public void testSetTimeZoneWithAutoTimeZoneOn() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME_ZONE, 0))
+                .thenReturn(1);
+        assertFalse(dpm.setTimeZone(admin1, "Asia/Shanghai"));
+    }
+
     public void testGetLastBugReportRequestTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
index 9702118..7e11e87 100644 (file)
@@ -30,8 +30,12 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
+import android.support.annotation.NonNull;
 import android.test.mock.MockContext;
 import android.util.ArrayMap;
+import android.util.ExceptionUtils;
+
+import com.android.internal.util.FunctionalUtils;
 
 import org.junit.Assert;
 
@@ -95,6 +99,21 @@ public class DpmMockContext extends MockContext {
             callingPid = (int) token;
         }
 
+        public void withCleanCallingIdentity(@NonNull FunctionalUtils.ThrowingRunnable action) {
+            long callingIdentity = clearCallingIdentity();
+            Throwable throwableToPropagate = null;
+            try {
+                action.run();
+            } catch (Throwable throwable) {
+                throwableToPropagate = throwable;
+            } finally {
+                restoreCallingIdentity(callingIdentity);
+                if (throwableToPropagate != null) {
+                    throw ExceptionUtils.propagate(throwableToPropagate);
+                }
+            }
+        }
+
         public int getCallingUid() {
             return callingUid;
         }