diff options
| -rw-r--r-- | api/current.txt | 21 | ||||
| -rw-r--r-- | api/system-current.txt | 24 | ||||
| -rw-r--r-- | core/java/android/app/admin/DeviceInitializerStatus.java | 177 | ||||
| -rw-r--r-- | core/java/android/app/admin/DevicePolicyManager.java | 54 | ||||
| -rw-r--r-- | core/java/android/app/admin/IDevicePolicyManager.aidl | 2 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 7 | ||||
| -rw-r--r-- | services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java | 34 |
7 files changed, 319 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index bec686d..533682f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5615,6 +5615,26 @@ package android.app.admin { field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE"; } + public class DeviceInitializerStatus { + method public static boolean isCustomStatus(int); + method public static boolean isErrorStatus(int); + method public static boolean isHighPriority(int); + field public static final int FLAG_STATUS_CUSTOM = 33554432; // 0x2000000 + field public static final int FLAG_STATUS_ERROR = 16777216; // 0x1000000 + field public static final int FLAG_STATUS_HIGH_PRIORITY = 134217728; // 0x8000000 + field public static final int FLAG_STATUS_RESERVED = 67108864; // 0x4000000 + field public static final int STATUS_ERROR_CONNECT_WIFI = 16777237; // 0x1000015 + field public static final int STATUS_ERROR_DELETE_APPS = 16777242; // 0x100001a + field public static final int STATUS_ERROR_DOUBLE_BUMP = 16777246; // 0x100001e + field public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = 16777239; // 0x1000017 + field public static final int STATUS_ERROR_INSTALL_PACKAGE = 16777240; // 0x1000018 + field public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING = 16777238; // 0x1000016 + field public static final int STATUS_ERROR_SET_DEVICE_POLICY = 16777241; // 0x1000019 + field public static final int STATUS_STATE_CONNECT_BLUETOOTH_PROXY = 134217736; // 0x8000008 + field public static final int STATUS_STATE_DEVICE_PROVISIONED = 134217738; // 0x800000a + field public static final int STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY = 134217737; // 0x8000009 + } + public class DevicePolicyManager { method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int); method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); @@ -5678,6 +5698,7 @@ package android.app.admin { method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean resetPassword(java.lang.String, int); + method public void sendDeviceInitializerStatus(int, java.lang.String); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle); diff --git a/api/system-current.txt b/api/system-current.txt index 2cfa9a7..7698f8e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5710,6 +5710,26 @@ package android.app.admin { field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE"; } + public class DeviceInitializerStatus { + method public static boolean isCustomStatus(int); + method public static boolean isErrorStatus(int); + method public static boolean isHighPriority(int); + field public static final int FLAG_STATUS_CUSTOM = 33554432; // 0x2000000 + field public static final int FLAG_STATUS_ERROR = 16777216; // 0x1000000 + field public static final int FLAG_STATUS_HIGH_PRIORITY = 134217728; // 0x8000000 + field public static final int FLAG_STATUS_RESERVED = 67108864; // 0x4000000 + field public static final int STATUS_ERROR_CONNECT_WIFI = 16777237; // 0x1000015 + field public static final int STATUS_ERROR_DELETE_APPS = 16777242; // 0x100001a + field public static final int STATUS_ERROR_DOUBLE_BUMP = 16777246; // 0x100001e + field public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = 16777239; // 0x1000017 + field public static final int STATUS_ERROR_INSTALL_PACKAGE = 16777240; // 0x1000018 + field public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING = 16777238; // 0x1000016 + field public static final int STATUS_ERROR_SET_DEVICE_POLICY = 16777241; // 0x1000019 + field public static final int STATUS_STATE_CONNECT_BLUETOOTH_PROXY = 134217736; // 0x8000008 + field public static final int STATUS_STATE_DEVICE_PROVISIONED = 134217738; // 0x800000a + field public static final int STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY = 134217737; // 0x8000009 + } + public class DevicePolicyManager { method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int); method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); @@ -5781,6 +5801,7 @@ package android.app.admin { method public boolean removeCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String); method public boolean removeUser(android.content.ComponentName, android.os.UserHandle); method public boolean resetPassword(java.lang.String, int); + method public void sendDeviceInitializerStatus(int, java.lang.String); method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean); method public deprecated boolean setActiveProfileOwner(android.content.ComponentName, java.lang.String) throws java.lang.IllegalArgumentException; method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean); @@ -5826,6 +5847,7 @@ package android.app.admin { 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_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"; field public static final java.lang.String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER"; field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION"; @@ -5836,6 +5858,8 @@ package android.app.admin { field public static final int ENCRYPTION_STATUS_UNSUPPORTED = 0; // 0x0 field public static final java.lang.String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION"; field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN"; + field public static final java.lang.String EXTRA_DEVICE_INITIALIZER_STATUS_CODE = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE"; + field public static final java.lang.String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION"; field public static final java.lang.String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME"; field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE"; field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE"; diff --git a/core/java/android/app/admin/DeviceInitializerStatus.java b/core/java/android/app/admin/DeviceInitializerStatus.java new file mode 100644 index 0000000..b58711c --- /dev/null +++ b/core/java/android/app/admin/DeviceInitializerStatus.java @@ -0,0 +1,177 @@ +/* + * 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; + +/** + * Defines constants designating device provisioning status used with {@link + * android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)}. + * + * This class contains flag constants that define special status codes: + * <ul> + * <li>{@link #FLAG_STATUS_ERROR} is used to define provisioning error status codes + * <li>{@link #FLAG_STATUS_CUSTOM} is used to define custom status codes + * <li>{@link #FLAG_STATUS_HIGH_PRIORITY} is used to define high priority status codes + * </ul> + * + * <p>Status codes used by ManagedProvisioning are also defined in this class. These status codes + * include provisioning errors and status codes. + * <ul> + * <li>{@link #STATUS_ERROR_CONNECT_WIFI} + * <li>{@link #STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING} + * <li>{@link #STATUS_ERROR_DOWNLOAD_PACKAGE} + * <li>{@link #STATUS_ERROR_INSTALL_PACKAGE} + * <li>{@link #STATUS_ERROR_SET_DEVICE_POLICY} + * <li>{@link #STATUS_ERROR_DELETE_APPS} + * <li>{@link #STATUS_ERROR_DOUBLE_BUMP} + * <li>{@link #STATUS_STATE_CONNECT_BLUETOOTH_PROXY} + * <li>{@link #STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY} + * <li>{@link #STATUS_STATE_DEVICE_PROVISIONED} + * </ul> + */ +public class DeviceInitializerStatus { + /** + * A flag used to designate an error status. + * + * <p>This flag is used with {@code statusCode} values sent through + * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)} + * @see #isErrorStatus(int) + */ + public static final int FLAG_STATUS_ERROR = 0x01000000; + + /** + * A flag used to designate a custom status. Custom status codes will be defined by device + * initializer agents. + * + * <p>This flag is used with {@code statusCode} values sent through + * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)} + * @see #isCustomStatus(int) + */ + public static final int FLAG_STATUS_CUSTOM = 0x02000000; + + /** + * A bit flag used to designate a reserved status. Reserved status codes will not be defined + * in AOSP. + * + * <p>This flag is used with {@code statusCode} values sent through + * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)} + */ + public static final int FLAG_STATUS_RESERVED = 0x04000000; + + /** + * A flag used to indicate that a status message is high priority. + * + * <p>This flag is used with {@code statusCode} values sent through + * {@link android.app.admin.DevicePolicyManager#sendDeviceInitializerStatus(int,String)} + * @see #isHighPriority(int) + */ + public static final int FLAG_STATUS_HIGH_PRIORITY = 0x08000000; + + /** + * Device provisioning status code that indicates that a device is connecting to establish + * a Bluetooth network proxy. + */ + public static final int STATUS_STATE_CONNECT_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 8; + + /** + * Device provisioning status code that indicates that a connected Bluetooth network proxy + * is being shut down. + */ + public static final int STATUS_STATE_DISCONNECT_BLUETOOTH_PROXY = FLAG_STATUS_HIGH_PRIORITY | 9; + + /** + * Device provisioning status code that indicates that a device has been successfully + * provisioned. + */ + public static final int STATUS_STATE_DEVICE_PROVISIONED = FLAG_STATUS_HIGH_PRIORITY | 10; + + /** + * Device provisioning error status code that indicates that a device could not connect to + * a Wi-Fi network. + */ + public static final int STATUS_ERROR_CONNECT_WIFI = FLAG_STATUS_ERROR | 21; + + /** + * Device provisioning error status indicating that factory reset protection is enabled on + * the provisioned device and cannot be disabled with the provided data. + */ + public static final int STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING = + FLAG_STATUS_ERROR | 22; + + /** + * Device provisioning error status indicating that device administrator and device initializer + * packages could not be downloaded and verified successfully. + */ + public static final int STATUS_ERROR_DOWNLOAD_PACKAGE = FLAG_STATUS_ERROR | 23; + + /** + * Device provisioning error status indicating that device owner and device initializer packages + * could not be installed. + */ + public static final int STATUS_ERROR_INSTALL_PACKAGE = FLAG_STATUS_ERROR | 24; + + /** + * Device provisioning error status indicating that the device owner or device initializer + * components could not be set. + */ + public static final int STATUS_ERROR_SET_DEVICE_POLICY = FLAG_STATUS_ERROR | 25; + + /** + * Device provisioning error status indicating that deleting non-required applications during + * provisioning failed. + */ + public static final int STATUS_ERROR_DELETE_APPS = FLAG_STATUS_ERROR | 26; + + /** + * Device provisioning error status code that indicates that a provisioning attempt has failed + * because the device has already been provisioned or that provisioning has already started. + */ + public static final int STATUS_ERROR_DOUBLE_BUMP = FLAG_STATUS_ERROR | 30; + + /** + * Determine if the specified status code represents an error status. + * @param statusCode status code to check + * @return {@code true} if the status code is an error status code + */ + public static boolean isErrorStatus(int statusCode) { + return isFlagSet(statusCode, FLAG_STATUS_ERROR); + } + + /** + * Determine if the specified status code is a custom status. Custom status codes are defined + * and sent by device initialization agents. + * @param statusCode status code to check + * @return {@code true} if the status code is a custom status code + */ + public static boolean isCustomStatus(int statusCode) { + return isFlagSet(statusCode, FLAG_STATUS_CUSTOM); + } + + /** + * Determine if the specified status code is a high priority status code. + * @param statusCode status code to check + * @return {@code true} if the status code is a high priority status code + */ + public static boolean isHighPriority(int statusCode) { + return isFlagSet(statusCode, FLAG_STATUS_HIGH_PRIORITY); + } + + private static boolean isFlagSet(int statusCode, int flag) { + return (statusCode & flag) != 0; + } + + private DeviceInitializerStatus() {} +} diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 68f4707..26b1b36 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -651,6 +651,45 @@ public class DevicePolicyManager { = "android.app.action.SET_PROFILE_OWNER"; /** + * Protected broadcast action that will be sent to managed provisioning to notify it that a + * status update has been reported by the device initializer. The status update will be + * reported to the remote setup device over Bluetooth. + * + * <p>Broadcasts with this action must supply a + * {@linkplain DeviceInitializerStatus#isCustomStatus(int) custom} status code in the + * {@link EXTRA_DEVICE_INITIALIZER_STATUS_CODE} extra. + * + * <p>Broadcasts may optionally contain a description in the + * {@link EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION} extra. + * @hide + */ + @SystemApi + public static final String ACTION_SEND_DEVICE_INITIALIZER_STATUS + = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS"; + + /** + * An integer extra that contains the status code that defines a status update. This extra must + * sent as part of a broadcast with an action of {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}. + * + * <p>The status code sent with this extra must be a custom status code as defined by + * {@link DeviceInitializerStatus#isCustomStatus(int)}. + * @hide + */ + @SystemApi + public static final String EXTRA_DEVICE_INITIALIZER_STATUS_CODE + = "android.app.extra.DEVICE_INITIALIZER_STATUS_CODE"; + + /** + * A {@code String} extra that contains an optional description accompanying a status update. + * This extra my be sent as part of a broadcast with an action of + * {@code ACTION_SEND_DEVICE_INITIALIZER_STATUS}. + * @hide + */ + @SystemApi + public static final String EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION + = "android.app.extra.DEVICE_INITIALIZER_STATUS_DESCRIPTION"; + + /** * @hide * Name of the profile owner admin that controls the user. */ @@ -4012,4 +4051,19 @@ public class DevicePolicyManager { Log.w(TAG, "Could not set the user icon ", re); } } + + /** + * Called by device initializer to send a provisioning status update to the remote setup device. + * + * @param statusCode a custom status code value as defined by + * {@link DeviceInitializerStatus#isCustomStatus(int)}. + * @param description custom description of the status code sent + */ + public void sendDeviceInitializerStatus(int statusCode, String description) { + try { + mService.sendDeviceInitializerStatus(statusCode, description); + } catch (RemoteException re) { + Log.w(TAG, "Could not send device initializer status", re); + } + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index c68311e..75b97a8 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -213,4 +213,6 @@ interface IDevicePolicyManager { ComponentName getDeviceInitializerComponent(); void setUserIcon(in ComponentName admin, in Bitmap icon); + + void sendDeviceInitializerStatus(int statusCode, String description); } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7c5d194..4a1be2d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -87,6 +87,7 @@ <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" /> <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" /> <protected-broadcast android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" /> + <protected-broadcast android:name="android.app.action.SEND_DEVICE_INITIALIZER_STATUS" /> <protected-broadcast android:name="android.appwidget.action.APPWIDGET_UPDATE_OPTIONS" /> <protected-broadcast android:name="android.appwidget.action.APPWIDGET_DELETED" /> @@ -2374,6 +2375,12 @@ <permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" android:protectionLevel="signature" /> + <!-- Allows receiving status updates from a device initializer. + @hide Not for use by third-party applications. --> + <permission android:name="android.permission.RECEIVE_DEVICE_INITIALIZER_STATUS" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="signature" /> + <!-- The system process is explicitly the only one allowed to launch the confirmation UI for full backup/restore --> <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/> diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index bb3085e..c500d79 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -5715,6 +5715,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public void sendDeviceInitializerStatus(int statusCode, String description) { + synchronized (this) { + String packageName = getDeviceInitializer(); + if (packageName == null) { + throw new SecurityException("No device initializers"); + } + UserHandle callingUser = Binder.getCallingUserHandle(); + int deviceInitializerUid = -1; + try { + deviceInitializerUid = mContext.getPackageManager().getPackageUid( + packageName, callingUser.getIdentifier()); + } catch (NameNotFoundException e) { + throw new SecurityException(e); + } + if (Binder.getCallingUid() != deviceInitializerUid) { + throw new SecurityException("Caller must be a device initializer"); + } + long id = Binder.clearCallingIdentity(); + try { + Intent intent = new Intent( + DevicePolicyManager.ACTION_SEND_DEVICE_INITIALIZER_STATUS); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_INITIALIZER_STATUS_CODE, + statusCode); + intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_INITIALIZER_STATUS_DESCRIPTION, + description); + mContext.sendBroadcastAsUser(intent, callingUser, + android.Manifest.permission.RECEIVE_DEVICE_INITIALIZER_STATUS); + } finally { + restoreCallingIdentity(id); + } + } + } + /** * We need to update the internal state of whether a user has completed setup once. After * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes |
