diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:25:32 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-10 07:25:32 +0000 |
commit | 1b3f4ae5968885117ac198695a424fda99730f1a (patch) | |
tree | 8236fd9b0b9af80c6821bb775caabec8b0d0a140 | |
parent | a169fa4647c818fbebe1a24ebbc18ec746133adb (diff) | |
parent | 841d5199e1d1c64e7853fd953eed5247780908c1 (diff) | |
download | Provision-android14-mainline-os-statsd-release.tar.gz |
Snap for 8564071 from 841d5199e1d1c64e7853fd953eed5247780908c1 to mainline-os-statsd-releaseaml_sta_341615000aml_sta_341511040aml_sta_341410000aml_sta_341311010aml_sta_341114000aml_sta_341111000aml_sta_341010020aml_sta_340912000aml_sta_340911000aml_sta_331910000aml_sta_331811000aml_sta_331711010aml_sta_331610000aml_sta_331511000aml_sta_331410000aml_sta_331311000aml_sta_331010010aml_sta_330910000aml_net_341111030android14-mainline-os-statsd-releaseandroid13-mainline-os-statsd-release
Change-Id: Ib06102d80102396ff191b9ba48ceb7825e5219c7
-rw-r--r-- | Android.bp | 5 | ||||
-rw-r--r-- | AndroidManifest.xml | 29 | ||||
-rw-r--r-- | MODULE_LICENSE_APACHE2 | 0 | ||||
-rw-r--r-- | NOTICE | 190 | ||||
-rw-r--r-- | PREUPLOAD.cfg | 7 | ||||
-rw-r--r-- | src/com/android/provision/DefaultActivity.java | 208 | ||||
-rw-r--r-- | src/com/android/provision/DpcInfo.java | 85 | ||||
-rw-r--r-- | src/com/android/provision/Utils.java | 81 |
8 files changed, 401 insertions, 204 deletions
@@ -1,3 +1,8 @@ +package { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + android_app { name: "Provision", srcs: ["**/*.java"], diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8360578..11f85c0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="UTF-8"?> +<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2008 The Android Open Source Project @@ -14,25 +14,32 @@ See the License for the specific language governing permissions and limitations under the License. --> + <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.provision"> + package="com.android.provision"> - <original-package android:name="com.android.provision" /> + <original-package android:name="com.android.provision"/> <!-- For miscellaneous settings --> - <uses-permission android:name="android.permission.WRITE_SETTINGS" /> - <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <uses-permission android:name="android.permission.WRITE_SETTINGS"/> + <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/> + + <!-- To start the device owner provisioning workflow --> + <uses-permission android:name="android.permission.DISPATCH_PROVISIONING_MESSAGE"/> + + <!-- To factory reset if provisioning failed --> + <uses-permission android:name="android.permission.MASTER_CLEAR"/> <application> <activity android:name="DefaultActivity" - android:excludeFromRecents="true"> + android:excludeFromRecents="true" + android:exported="true"> <intent-filter android:priority="1"> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.HOME" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.SETUP_WIZARD" /> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.HOME"/> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.SETUP_WIZARD"/> </intent-filter> </activity> </application> </manifest> - diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29..0000000 --- a/MODULE_LICENSE_APACHE2 +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, 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. - - 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. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg new file mode 100644 index 0000000..38f9800 --- /dev/null +++ b/PREUPLOAD.cfg @@ -0,0 +1,7 @@ +[Hook Scripts] +checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} +ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES} + +[Builtin Hooks] +commit_msg_changeid_field = true +commit_msg_test_field = true diff --git a/src/com/android/provision/DefaultActivity.java b/src/com/android/provision/DefaultActivity.java index 031f3b1..92720e3 100644 --- a/src/com/android/provision/DefaultActivity.java +++ b/src/com/android/provision/DefaultActivity.java @@ -16,33 +16,235 @@ package com.android.provision; +import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; +import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME; +import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION; +import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM; +import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER; + +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_MODE; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_MODE; +import static com.android.provision.Utils.TAG; +import static com.android.provision.Utils.getSettings; + import android.app.Activity; +import android.app.AlertDialog; +import android.app.admin.DevicePolicyManager; import android.content.ComponentName; +import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; import android.provider.Settings; +import android.util.Log; /** - * Application that sets the provisioned bit, like SetupWizard does. + * Application that sets the provisioned bit, like {@code SetupWizard} does. + * + * <p>By default, it silently provisions the device, but it can also be used to provision + * {@code DeviceOwner}. For example, to set the {@code TestDPC} app, run the steps below: + * <pre><code> + adb root + adb install PATH_TO_TESTDPC_APK + adb shell settings put secure tmp_provision_set_do 1 + adb shell settings put secure tmp_provision_package com.afwsamples.testdpc + adb shell settings put secure tmp_provision_receiver com.afwsamples.testdpc.DeviceAdminReceiver + adb shell settings put secure tmp_provision_trigger 2 + adb shell rm /data/system/device_policies.xml + adb shell settings put global device_provisioned 0 + adb shell settings put secure user_setup_complete 0 + adb shell pm enable com.android.provision + adb shell pm enable com.android.provision/.DefaultActivity + adb shell stop && adb shell start + + // You might also need to run: + adb shell am start com.android.provision/.DefaultActivity + + * </code></pre> */ public class DefaultActivity extends Activity { + // TODO(b/170333009): copied from ManagedProvisioning app, as they're hidden; + private static final String PROVISION_FINALIZATION_INSIDE_SUW = + "android.app.action.PROVISION_FINALIZATION_INSIDE_SUW"; + private static final int RESULT_CODE_PROFILE_OWNER_SET = 122; + private static final int RESULT_CODE_DEVICE_OWNER_SET = 123; + + private static final int REQUEST_CODE_STEP1 = 42; + private static final int REQUEST_CODE_STEP2_PO = 43; + private static final int REQUEST_CODE_STEP2_DO = 44; + @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); + boolean provisionDeviceOwner = getSettings(getContentResolver(), SETTINGS_PROVISION_DO_MODE, + DEFAULT_SETTINGS_PROVISION_DO_MODE) == 1; + + if (provisionDeviceOwner) { + provisionDeviceOwner(); + return; + } + finishSetup(); + } + + private void finishSetup() { + setProvisioningState(); + disableSelfAndFinish(); + } + + private void setProvisioningState() { + Log.i(TAG, "Setting provisioning state"); // Add a persistent setting to allow other apps to know the device has been provisioned. Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1); Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1); + } + private void disableSelfAndFinish() { // remove this activity from the package manager. PackageManager pm = getPackageManager(); ComponentName name = new ComponentName(this, DefaultActivity.class); + Log.i(TAG, "Disabling itself (" + name + ")"); pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); - // terminate the activity. finish(); } -} + private void provisionDeviceOwner() { + if (!getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) { + Log.e(TAG, "Cannot set up device owner because device does not have the " + + PackageManager.FEATURE_DEVICE_ADMIN + " feature"); + finishSetup(); + return; + } + DevicePolicyManager dpm = getSystemService(DevicePolicyManager.class); + if (!dpm.isProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE)) { + Log.e(TAG, "DeviceOwner provisioning is not allowed, most like device is already " + + "provisioned"); + finishSetup(); + return; + } + + DpcInfo dpcInfo = new DpcInfo(getContentResolver()); + Intent intent = new Intent(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE); + intent.putExtra(EXTRA_PROVISIONING_TRIGGER, dpcInfo.trigger); + intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME, + dpcInfo.getReceiverComponentName()); + if (dpcInfo.checkSum != null) { + intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM, dpcInfo.checkSum); + } + if (dpcInfo.downloadUrl != null) { + intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION, + dpcInfo.downloadUrl); + } + + Log.i(TAG, "Provisioning device with " + dpcInfo + ". Intent: " + intent); + startActivityForResult(intent, REQUEST_CODE_STEP1); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.d(TAG, "onActivityResult(): request=" + requestCode + ", result=" + + resultCodeToString(resultCode) + ", data=" + data); + + switch (requestCode) { + case REQUEST_CODE_STEP1: + onProvisioningStep1Result(resultCode); + break; + case REQUEST_CODE_STEP2_PO: + case REQUEST_CODE_STEP2_DO: + onProvisioningStep2Result(requestCode, resultCode); + break; + default: + showErrorMessage("onActivityResult(): invalid request code " + requestCode); + } + } + + private void onProvisioningStep1Result(int resultCode) { + int requestCodeStep2; + switch (resultCode) { + case RESULT_CODE_PROFILE_OWNER_SET: + requestCodeStep2 = REQUEST_CODE_STEP2_PO; + break; + case RESULT_CODE_DEVICE_OWNER_SET: + requestCodeStep2 = REQUEST_CODE_STEP2_DO; + break; + default: + factoryReset("invalid response from " + + ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE + ": " + + resultCodeToString(resultCode)); + return; + } + Intent intent = new Intent(PROVISION_FINALIZATION_INSIDE_SUW) + .addCategory(Intent.CATEGORY_DEFAULT); + Log.i(TAG, "Finalizing DPC with " + intent); + startActivityForResult(intent, requestCodeStep2); + } + + private void onProvisioningStep2Result(int requestCode, int resultCode) { + // Must set state before launching the intent that finalize the DPC, because the DPC + // implementation might not remove the back button + setProvisioningState(); + + boolean doMode = requestCode == REQUEST_CODE_STEP2_DO; + if (resultCode != RESULT_OK) { + factoryReset("invalid response from " + PROVISION_FINALIZATION_INSIDE_SUW + ": " + + resultCodeToString(resultCode)); + return; + } + + Log.i(TAG, (doMode ? "Device owner" : "Profile owner") + " mode provisioned!"); + disableSelfAndFinish(); + } + + private static String resultCodeToString(int resultCode) { + StringBuilder result = new StringBuilder(); + switch (resultCode) { + case RESULT_OK: + result.append("RESULT_OK"); + break; + case RESULT_CANCELED: + result.append("RESULT_CANCELED"); + break; + case RESULT_FIRST_USER: + result.append("RESULT_FIRST_USER"); + break; + case RESULT_CODE_PROFILE_OWNER_SET: + result.append("RESULT_CODE_PROFILE_OWNER_SET"); + break; + case RESULT_CODE_DEVICE_OWNER_SET: + result.append("RESULT_CODE_DEVICE_OWNER_SET"); + break; + default: + result.append("UNKNOWN_CODE"); + } + return result.append('(').append(resultCode).append(')').toString(); + } + + private void showErrorMessage(String message) { + Log.e(TAG, "Error: " + message); + } + + private void factoryReset(String reason) { + new AlertDialog.Builder(this) + .setMessage("Device owner provisioning failed (" + reason + + ") and device must be factory reset") + .setPositiveButton("Reset", (d, w) -> sendFactoryResetIntent(reason)) + .setOnDismissListener((d) -> sendFactoryResetIntent(reason)) + .show(); + } + + private void sendFactoryResetIntent(String reason) { + Log.e(TAG, "Factory resetting: " + reason); + Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); + intent.setPackage("android"); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.putExtra(Intent.EXTRA_REASON, reason); + + sendBroadcast(intent); + + // Just in case the factory reset request fails... + finishSetup(); + } +} diff --git a/src/com/android/provision/DpcInfo.java b/src/com/android/provision/DpcInfo.java new file mode 100644 index 0000000..af38d4b --- /dev/null +++ b/src/com/android/provision/DpcInfo.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2020 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.provision; + +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_CHECKSUM; +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER; +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_URL; +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_PKG; +import static com.android.provision.Utils.DEFAULT_SETTINGS_PROVISION_DO_RECEIVER; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_CHECKSUM; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_DOWNLOAD_URL; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_PKG; +import static com.android.provision.Utils.SETTINGS_PROVISION_DO_RECEIVER; +import static com.android.provision.Utils.getSettings; + +import android.content.ComponentName; +import android.content.ContentResolver; + +import java.util.Objects; + +/** + * Info about a Device Policy Controller app. + */ +final class DpcInfo { + + public final String packageName; + private final String mReceiverName; + public final String checkSum; + public final String downloadUrl; + public final int trigger; + + DpcInfo(ContentResolver resolver) { + this(getSettings(resolver, SETTINGS_PROVISION_DO_PKG, DEFAULT_SETTINGS_PROVISION_DO_PKG), + getSettings(resolver, SETTINGS_PROVISION_DO_RECEIVER, + DEFAULT_SETTINGS_PROVISION_DO_RECEIVER), + getSettings(resolver, SETTINGS_PROVISION_DO_CHECKSUM, + DEFAULT_SETTINGS_PROVISION_DO_CHECKSUM), + getSettings(resolver, SETTINGS_PROVISION_DO_DOWNLOAD_URL, + DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_URL), + getSettings(resolver, SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER, + DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER)); + } + + private DpcInfo(String packageName, String receiverName, String checkSum, String downloadUrl, + int trigger) { + this.packageName = Objects.requireNonNull(packageName, + "packageName (" + SETTINGS_PROVISION_DO_PKG + ") cannot be null"); + this.mReceiverName = Objects.requireNonNull(receiverName, + "receiverName(" + SETTINGS_PROVISION_DO_RECEIVER + ") cannot be null"); + this.checkSum = checkSum; + this.downloadUrl = downloadUrl; + this.trigger = trigger; + } + + /*** + * Gets the name of the admin receiver. + */ + public ComponentName getReceiverComponentName() { + return new ComponentName(packageName, mReceiverName); + } + + @Override + public String toString() { + return "DpcInfo[package=" + packageName + + ", receiver=" + getReceiverComponentName() + + ", checkSum=" + checkSum + + ", downloadUrl=" + downloadUrl + + ", trigger=" + trigger + + "]"; + } +} diff --git a/src/com/android/provision/Utils.java b/src/com/android/provision/Utils.java new file mode 100644 index 0000000..b26a0b4 --- /dev/null +++ b/src/com/android/provision/Utils.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 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.provision; + +import android.content.ContentResolver; +import android.provider.Settings; +import android.util.Log; + +/** + * Utility helpers. + */ +final class Utils { + + static final String TAG = "Provision"; + + private static final String BASE_SETTINGS = "tmp_provision_"; + static final String SETTINGS_PROVISION_DO_MODE = BASE_SETTINGS + "set_do"; + static final String SETTINGS_PROVISION_DO_PKG = BASE_SETTINGS + "package"; + static final String SETTINGS_PROVISION_DO_RECEIVER = BASE_SETTINGS + "receiver"; + static final String SETTINGS_PROVISION_DO_CHECKSUM = BASE_SETTINGS + "checksum"; + static final String SETTINGS_PROVISION_DO_DOWNLOAD_URL = BASE_SETTINGS + "download_url"; + static final String SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER = BASE_SETTINGS + "trigger"; + + // Values below should be merged as null / 0, but can be changed locally to make it easier + // to trigger device owner provisioning (see example below). + static final int DEFAULT_SETTINGS_PROVISION_DO_MODE = 0; + static final String DEFAULT_SETTINGS_PROVISION_DO_PKG = null; + static final String DEFAULT_SETTINGS_PROVISION_DO_RECEIVER = null; + static final int DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER = 0; + static final String DEFAULT_SETTINGS_PROVISION_DO_CHECKSUM = null; + static final String DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_URL = null; + + // Use these constants to trigger device owner provisioning using the TestDPC app (notice that + // it must be manually installed in the device). +// static final int DEFAULT_SETTINGS_PROVISION_DO_MODE = 1; +// static final String DEFAULT_SETTINGS_PROVISION_DO_PKG = "com.afwsamples.testdpc"; +// static final String DEFAULT_SETTINGS_PROVISION_DO_RECEIVER = +// "com.afwsamples.testdpc.DeviceAdminReceiver"; +// static final int DEFAULT_SETTINGS_PROVISION_DO_DOWNLOAD_TRIGGER = +// android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE; + + + static String getSettings(ContentResolver resolver, String property, + String overriddenValue) { + if (overriddenValue != null) { + Log.w(TAG, "Using OVERRIDDEN value " + overriddenValue + " for property " + property); + return overriddenValue; + } + String value = Settings.Secure.getString(resolver, property); + Log.w(TAG, "Using value " + overriddenValue + " for property " + property); + return value; + } + + static int getSettings(ContentResolver resolver, String property, + int overriddenValue) { + if (overriddenValue != 0) { + Log.w(TAG, "Using OVERRIDDEN value " + overriddenValue + " for property " + property); + return overriddenValue; + } + int value = Settings.Secure.getInt(resolver, property, overriddenValue); + Log.w(TAG, "Using value " + overriddenValue + " for property " + property); + return value; + } + + private Utils() { + throw new UnsupportedOperationException("contains only static members"); + } +} |