diff options
author | Rubin Xu <rubinxu@google.com> | 2015-04-14 09:16:27 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-04-14 09:16:28 +0000 |
commit | c9c9f7b40ec77217ce595fd152a505481326dc9a (patch) | |
tree | 3005503c6fec2b9f69a3919a4c622cf82dac0cd0 | |
parent | 0c606812c5102fd19eda4b3e1ffbc9e61fec6430 (diff) | |
parent | 8027a4ffc285ba39df3a262abfff1cfdd6dd31db (diff) | |
download | frameworks_base-c9c9f7b40ec77217ce595fd152a505481326dc9a.zip frameworks_base-c9c9f7b40ec77217ce595fd152a505481326dc9a.tar.gz frameworks_base-c9c9f7b40ec77217ce595fd152a505481326dc9a.tar.bz2 |
Merge "Add setOtaPolicy/getOtaPolicy API in DPMS"
-rw-r--r-- | api/current.txt | 20 | ||||
-rw-r--r-- | api/system-current.txt | 20 | ||||
-rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 53 | ||||
-rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 2 | ||||
-rw-r--r-- | core/java/android/app/admin/OtaPolicy.java | 179 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 1 | ||||
-rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java | 30 | ||||
-rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 22 |
8 files changed, 327 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index cfe438c..0db2319 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5664,6 +5664,7 @@ package android.app.admin { method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); + method public android.app.admin.OtaPolicy getOtaPolicy(); method public long getPasswordExpiration(android.content.ComponentName); method public long getPasswordExpirationTimeout(android.content.ComponentName); method public int getPasswordHistoryLength(android.content.ComponentName); @@ -5716,6 +5717,7 @@ package android.app.admin { method public void setMasterVolumeMuted(android.content.ComponentName, boolean); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); method public void setMaximumTimeToLock(android.content.ComponentName, long); + method public void setOtaPolicy(android.content.ComponentName, android.app.admin.OtaPolicy); method public void setPasswordExpirationTimeout(android.content.ComponentName, long); method public void setPasswordHistoryLength(android.content.ComponentName, int); method public void setPasswordMinimumLength(android.content.ComponentName, int); @@ -5745,6 +5747,7 @@ package android.app.admin { method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED"; + field public static final java.lang.String ACTION_OTA_POLICY_CHANGED = "android.app.action.OTA_POLICY_CHANGED"; field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE"; field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD"; field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION"; @@ -5812,6 +5815,23 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public class OtaPolicy { + ctor public OtaPolicy(); + method public int getInstallWindowEnd(); + method public int getInstallWindowStart(); + method public int getPolicyType(); + method public void setAutomaticInstallPolicy(); + method public void setPostponeInstallPolicy(); + method public void setWindowedInstallPolicy(int, int) throws android.app.admin.OtaPolicy.InvalidWindowException; + field public static final int TYPE_INSTALL_AUTOMATIC = 1; // 0x1 + field public static final int TYPE_INSTALL_WINDOWED = 2; // 0x2 + field public static final int TYPE_POSTPONE = 3; // 0x3 + } + + public static class OtaPolicy.InvalidWindowException extends java.lang.Exception { + ctor public OtaPolicy.InvalidWindowException(java.lang.String); + } + } package android.app.backup { diff --git a/api/system-current.txt b/api/system-current.txt index 0fbc580..9fd7b65 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5763,6 +5763,7 @@ package android.app.admin { method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName); method public long getMaximumTimeToLock(android.content.ComponentName); + method public android.app.admin.OtaPolicy getOtaPolicy(); method public long getPasswordExpiration(android.content.ComponentName); method public long getPasswordExpirationTimeout(android.content.ComponentName); method public int getPasswordHistoryLength(android.content.ComponentName); @@ -5820,6 +5821,7 @@ package android.app.admin { method public void setMasterVolumeMuted(android.content.ComponentName, boolean); method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int); method public void setMaximumTimeToLock(android.content.ComponentName, long); + method public void setOtaPolicy(android.content.ComponentName, android.app.admin.OtaPolicy); method public void setPasswordExpirationTimeout(android.content.ComponentName, long); method public void setPasswordHistoryLength(android.content.ComponentName, int); method public void setPasswordMinimumLength(android.content.ComponentName, int); @@ -5849,6 +5851,7 @@ package android.app.admin { method public void wipeData(int); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED"; + field public static final java.lang.String ACTION_OTA_POLICY_CHANGED = "android.app.action.OTA_POLICY_CHANGED"; field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE"; field public static final java.lang.String ACTION_SEND_DEVICE_INITIALIZER_STATUS = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS"; field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD"; @@ -5921,6 +5924,23 @@ package android.app.admin { field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2 } + public class OtaPolicy { + ctor public OtaPolicy(); + method public int getInstallWindowEnd(); + method public int getInstallWindowStart(); + method public int getPolicyType(); + method public void setAutomaticInstallPolicy(); + method public void setPostponeInstallPolicy(); + method public void setWindowedInstallPolicy(int, int) throws android.app.admin.OtaPolicy.InvalidWindowException; + field public static final int TYPE_INSTALL_AUTOMATIC = 1; // 0x1 + field public static final int TYPE_INSTALL_WINDOWED = 2; // 0x2 + field public static final int TYPE_POSTPONE = 3; // 0x3 + } + + public static class OtaPolicy.InvalidWindowException extends java.lang.Exception { + ctor public OtaPolicy.InvalidWindowException(java.lang.String); + } + } package android.app.backup { diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 260c7ff..dd64436 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -754,6 +754,14 @@ public class DevicePolicyManager { public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002; /** + * Broadcast action: notify that a new local OTA policy has been set by the device owner. + * The new policy can be retrieved by {@link #getOtaPolicy()}. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_OTA_POLICY_CHANGED = "android.app.action.OTA_POLICY_CHANGED"; + + + /** * Return true if the given administrator component is currently * active (enabled) in the system. */ @@ -4134,4 +4142,49 @@ public class DevicePolicyManager { Log.w(TAG, "Could not send device initializer status", re); } } + + /* + * Called by device owners to set a local OTA update policy. When a new OTA policy is set, + * {@link #ACTION_OTA_POLICY_CHANGED} is broadcasted. + * + * @param who Which {@link DeviceAdminReceiver} this request is associated with. All components + * in the device owner package can set OTA policies and the most recent policy takes effect. + * @param policy the new OTA policy, or null to clear the current policy. + * @see OtaPolicy + */ + public void setOtaPolicy(ComponentName who, OtaPolicy policy) { + if (mService != null) { + try { + if (policy != null) { + mService.setOtaPolicy(who, policy.getPolicyBundle()); + } else { + mService.setOtaPolicy(who, null); + } + } catch (RemoteException re) { + Log.w(TAG, "Error calling setOtaPolicy", re); + } + } + } + + /** + * Retrieve a local OTA update policy set previously by {@link #setOtaPolicy}. + * + * @return The current OTA policy object, or null if no policy is set or the system does not + * support managed OTA. + */ + public OtaPolicy getOtaPolicy() { + if (mService != null) { + try { + PersistableBundle bundle = mService.getOtaPolicy(); + if (bundle != null) { + return new OtaPolicy(bundle); + } else { + return null; + } + } catch (RemoteException re) { + Log.w(TAG, "Error calling getOtaPolicy", re); + } + } + return null; + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index e236010..332d59e 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -219,4 +219,6 @@ interface IDevicePolicyManager { void setUserIcon(in ComponentName admin, in Bitmap icon); void sendDeviceInitializerStatus(int statusCode, String description); + void setOtaPolicy(in ComponentName who, in PersistableBundle policy); + PersistableBundle getOtaPolicy(); } diff --git a/core/java/android/app/admin/OtaPolicy.java b/core/java/android/app/admin/OtaPolicy.java new file mode 100644 index 0000000..98581a7 --- /dev/null +++ b/core/java/android/app/admin/OtaPolicy.java @@ -0,0 +1,179 @@ +/* + * 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 android.app.admin; + +import android.annotation.IntDef; +import android.os.PersistableBundle; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A class that represents a local OTA policy set by the device owner. + * + * @see DevicePolicyManager#setOtaPolicy + * @see DevicePolicyManager#getOtaPolicy + */ +public class OtaPolicy { + + /** @hide */ + @IntDef({ + TYPE_INSTALL_AUTOMATIC, + TYPE_INSTALL_WINDOWED, + TYPE_POSTPONE}) + @Retention(RetentionPolicy.SOURCE) + @interface OtaPolicyType {} + + /** + * Install OTA update automatically as soon as one is available. + */ + public static final int TYPE_INSTALL_AUTOMATIC = 1; + + /** + * Install OTA update automatically within a daily maintenance window, for a maximum of two-week + * period. After that period the OTA will be installed automatically. + */ + public static final int TYPE_INSTALL_WINDOWED = 2; + + /** + * Incoming OTA will be blocked for a maximum of two weeks, after which it will be installed + * automatically. + */ + public static final int TYPE_POSTPONE = 3; + + private static final String KEY_POLICY_TYPE = "policy_type"; + private static final String KEY_INSTALL_WINDOW_START = "install_window_start"; + private static final String KEY_INSTALL_WINDOW_END = "install_window_end"; + + private PersistableBundle mPolicy; + + public OtaPolicy() { + mPolicy = new PersistableBundle(); + } + + /** + * Construct an OtaPolicy object from a bundle. + * @hide + */ + public OtaPolicy(PersistableBundle in) { + mPolicy = new PersistableBundle(in); + } + + /** + * Retrieve the underlying bundle where the policy is stored. + * @hide + */ + public PersistableBundle getPolicyBundle() { + return new PersistableBundle(mPolicy); + } + + /** + * Set the OTA policy to: install OTA update automatically as soon as one is available. + */ + public void setAutomaticInstallPolicy() { + mPolicy.clear(); + mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_AUTOMATIC); + } + + /** + * Set the OTA policy to: new OTA update will only be installed automatically when the system + * clock is inside a daily maintenance window. If the start and end times are the same, the + * window is considered to include the WHOLE 24 hours, that is, OTAs can install at any time. If + * the given window in invalid, a {@link OtaPolicy.InvalidWindowException} will be thrown. If + * start time is later than end time, the window is considered spanning midnight, i.e. end time + * donates a time on the next day. The maintenance window will last for two weeks, after which + * the OTA will be installed automatically. + * + * @param startTime the start of the maintenance window, measured as the number of minutes from + * midnight in the device's local time. Must be in the range of [0, 1440). + * @param endTime the end of the maintenance window, measured as the number of minutes from + * midnight in the device's local time. Must be in the range of [0, 1440). + */ + public void setWindowedInstallPolicy(int startTime, int endTime) throws InvalidWindowException{ + if (startTime < 0 || startTime >= 1440 || endTime < 0 || endTime >= 1440) { + throw new InvalidWindowException("startTime and endTime must be inside [0, 1440)"); + } + mPolicy.clear(); + mPolicy.putInt(KEY_POLICY_TYPE, TYPE_INSTALL_WINDOWED); + mPolicy.putInt(KEY_INSTALL_WINDOW_START, startTime); + mPolicy.putInt(KEY_INSTALL_WINDOW_END, endTime); + } + + /** + * Set the OTA policy to: block installation for a maximum period of two weeks. After the + * block expires the OTA will be installed automatically. + */ + public void setPostponeInstallPolicy() { + mPolicy.clear(); + mPolicy.putInt(KEY_POLICY_TYPE, TYPE_POSTPONE); + } + + /** + * Returns the type of OTA policy. + * + * @return an integer, either one of {@link #TYPE_INSTALL_AUTOMATIC}, + * {@link #TYPE_INSTALL_WINDOWED} and {@link #TYPE_POSTPONE}, or -1 if no policy has been set. + */ + @OtaPolicyType + public int getPolicyType() { + return mPolicy.getInt(KEY_POLICY_TYPE, -1); + } + + /** + * Get the start of the maintenance window. + * + * @return the start of the maintenance window measured as the number of minutes from midnight, + * or -1 if the policy does not have a maintenance window. + */ + public int getInstallWindowStart() { + if (getPolicyType() == TYPE_INSTALL_WINDOWED) { + return mPolicy.getInt(KEY_INSTALL_WINDOW_START, -1); + } else { + return -1; + } + } + + /** + * Get the end of the maintenance window. + * + * @return the end of the maintenance window measured as the number of minutes from midnight, + * or -1 if the policy does not have a maintenance window. + */ + public int getInstallWindowEnd() { + if (getPolicyType() == TYPE_INSTALL_WINDOWED) { + return mPolicy.getInt(KEY_INSTALL_WINDOW_END, -1); + } else { + return -1; + } + } + + @Override + public String toString() { + return mPolicy.toString(); + } + + /** + * Exception thrown by {@link OtaPolicy#setWindowedInstallPolicy(int, int)} in case the + * specified window is invalid. + */ + public static class InvalidWindowException extends Exception { + public InvalidWindowException(String reason) { + super(reason); + } + } +} + diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 4a1be2d..3d22e52 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -311,6 +311,7 @@ <protected-broadcast android:name="android.internal.policy.action.BURN_IN_PROTECTION" /> <protected-broadcast android:name="android.service.persistentdata.action.WIPE_IF_ALLOWED" /> + <protected-broadcast android:name="android.app.action.OTA_POLICY_CHANGED" /> <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> <!-- ====================================================================== --> diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java index c766183..2661643 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java @@ -22,6 +22,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Environment; +import android.os.PersistableBundle; import android.os.RemoteException; import android.util.AtomicFile; import android.util.Slog; @@ -59,6 +60,7 @@ class DeviceOwner { private static final String ATTR_PACKAGE = "package"; private static final String ATTR_COMPONENT_NAME = "component"; private static final String ATTR_USERID = "userId"; + private static final String TAG_OTA_POLICY = "ota-policy"; private AtomicFile fileForWriting; @@ -75,6 +77,9 @@ class DeviceOwner { // Internal state for the profile owner packages. private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>(); + // Local OTA policy controllable by device owner. + private PersistableBundle mOtaPolicy; + // Private default constructor. private DeviceOwner() { } @@ -187,6 +192,18 @@ class DeviceOwner { return mProfileOwners.keySet(); } + PersistableBundle getOtaPolicy() { + return mOtaPolicy; + } + + void setOtaPolicy(PersistableBundle otaPolicy) { + mOtaPolicy = otaPolicy; + } + + void clearOtaPolicy() { + mOtaPolicy = null; + } + boolean hasDeviceOwner() { return mDeviceOwner != null; } @@ -273,6 +290,8 @@ class DeviceOwner { profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName); } mProfileOwners.put(userId, profileOwnerInfo); + } else if (TAG_OTA_POLICY.equals(tag)) { + mOtaPolicy = PersistableBundle.restoreFromXml(parser); } else { throw new XmlPullParserException( "Unexpected tag in device owner file: " + tag); @@ -338,6 +357,17 @@ class DeviceOwner { out.endTag(null, TAG_PROFILE_OWNER); } } + + // Write OTA policy tag + if (mOtaPolicy != null) { + out.startTag(null, TAG_OTA_POLICY); + try { + mOtaPolicy.saveToXml(out); + } catch (XmlPullParserException e) { + Slog.e(TAG, "Failed to save OTA policy", e); + } + out.endTag(null, TAG_OTA_POLICY); + } out.endDocument(); out.flush(); finishWrite(outputStream); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 317c630..26c7130 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5926,4 +5926,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } return admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); } + + @Override + public void setOtaPolicy(ComponentName who, PersistableBundle policy) { + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + if (policy == null) { + mDeviceOwner.clearOtaPolicy(); + } else { + mDeviceOwner.setOtaPolicy(policy); + } + mDeviceOwner.writeOwnerFile(); + } + mContext.sendBroadcastAsUser(new Intent(DevicePolicyManager.ACTION_OTA_POLICY_CHANGED), + UserHandle.OWNER); + } + + @Override + public PersistableBundle getOtaPolicy() { + synchronized (this) { + return mDeviceOwner.getOtaPolicy(); + } + } } |