Transform NFC Intent to provisioning Intent
Generates a provisioning intent with the extra data from a nfc intent. Test: CTS tests are included in the other CL in this topic Bug: 192228539 Change-Id: I00ed374191bc3a48dcb336ed056395be59c445f5
This commit is contained in:
committed by
Antoan Angelov
parent
835c8181a7
commit
bb419eee4a
2
core/api/system-current.txt
Normal file → Executable file
2
core/api/system-current.txt
Normal file → Executable file
@@ -924,6 +924,7 @@ package android.app.admin {
|
||||
}
|
||||
|
||||
public class DevicePolicyManager {
|
||||
method @Nullable public android.content.Intent createProvisioningIntentFromNfcIntent(@NonNull android.content.Intent);
|
||||
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
|
||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
|
||||
@@ -972,6 +973,7 @@ package android.app.admin {
|
||||
field public static final int FLAG_SUPPORTED_MODES_PERSONALLY_OWNED = 2; // 0x2
|
||||
field public static final int PROVISIONING_TRIGGER_CLOUD_ENROLLMENT = 1; // 0x1
|
||||
field public static final int PROVISIONING_TRIGGER_MANAGED_ACCOUNT = 4; // 0x4
|
||||
field public static final int PROVISIONING_TRIGGER_NFC = 5; // 0x5
|
||||
field @Deprecated public static final int PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER = 3; // 0x3
|
||||
field public static final int PROVISIONING_TRIGGER_QR_CODE = 2; // 0x2
|
||||
field public static final int PROVISIONING_TRIGGER_UNSPECIFIED = 0; // 0x0
|
||||
|
||||
@@ -56,6 +56,7 @@ import android.graphics.Bitmap;
|
||||
import android.net.PrivateDnsConnectivityChecker;
|
||||
import android.net.ProxyInfo;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
@@ -1216,7 +1217,8 @@ public class DevicePolicyManager {
|
||||
PROVISIONING_TRIGGER_CLOUD_ENROLLMENT,
|
||||
PROVISIONING_TRIGGER_QR_CODE,
|
||||
PROVISIONING_TRIGGER_PERSISTENT_DEVICE_OWNER,
|
||||
PROVISIONING_TRIGGER_MANAGED_ACCOUNT
|
||||
PROVISIONING_TRIGGER_MANAGED_ACCOUNT,
|
||||
PROVISIONING_TRIGGER_NFC
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ProvisioningTrigger {}
|
||||
@@ -1254,6 +1256,7 @@ public class DevicePolicyManager {
|
||||
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
|
||||
* @see #PROVISIONING_TRIGGER_QR_CODE
|
||||
* @see #PROVISIONING_TRIGGER_MANAGED_ACCOUNT
|
||||
* @see #PROVISIONING_TRIGGER_NFC
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -1265,6 +1268,7 @@ public class DevicePolicyManager {
|
||||
* @see #PROVISIONING_TRIGGER_QR_CODE
|
||||
* @see #PROVISIONING_TRIGGER_MANAGED_ACCOUNT
|
||||
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
|
||||
* @see #PROVISIONING_TRIGGER_NFC
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -1276,6 +1280,7 @@ public class DevicePolicyManager {
|
||||
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
|
||||
* @see #PROVISIONING_TRIGGER_MANAGED_ACCOUNT
|
||||
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
|
||||
* @see #PROVISIONING_TRIGGER_NFC
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -1295,6 +1300,7 @@ public class DevicePolicyManager {
|
||||
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
|
||||
* @see #PROVISIONING_TRIGGER_QR_CODE
|
||||
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
|
||||
* @see #PROVISIONING_TRIGGER_NFC
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@@ -1308,11 +1314,24 @@ public class DevicePolicyManager {
|
||||
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
|
||||
* @see #PROVISIONING_TRIGGER_QR_CODE
|
||||
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
|
||||
* @see #PROVISIONING_TRIGGER_NFC
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int PROVISIONING_TRIGGER_MANAGED_ACCOUNT = 4;
|
||||
|
||||
/**
|
||||
* A value for {@link #EXTRA_PROVISIONING_TRIGGER} indicating that the provisioning is
|
||||
* triggered by tapping an NFC tag.
|
||||
* @see #PROVISIONING_TRIGGER_CLOUD_ENROLLMENT
|
||||
* @see #PROVISIONING_TRIGGER_QR_CODE
|
||||
* @see #PROVISIONING_TRIGGER_UNSPECIFIED
|
||||
* @see #PROVISIONING_TRIGGER_MANAGED_ACCOUNT
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int PROVISIONING_TRIGGER_NFC = 5;
|
||||
|
||||
/**
|
||||
* Flag for {@link #EXTRA_PROVISIONING_SUPPORTED_MODES} indicating that provisioning is
|
||||
* organization-owned.
|
||||
@@ -14009,4 +14028,33 @@ public class DevicePolicyManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent
|
||||
* from the provided {@code nfcIntent}.
|
||||
*
|
||||
* <p>Prerequisites to create the provisioning intent:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@code nfcIntent}'s action is {@link NfcAdapter#ACTION_NDEF_DISCOVERED}</li>
|
||||
* <li>{@code nfcIntent}'s NFC properties contain either
|
||||
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} or
|
||||
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} </li>
|
||||
* </ul>
|
||||
*
|
||||
* This method returns {@code null} if the prerequisites are not met or if an error occurs
|
||||
* when reading the NFC properties.
|
||||
*
|
||||
* @param nfcIntent the nfc intent generated from scanning a NFC tag
|
||||
* @return a {@link #ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} intent with
|
||||
* intent extras as read by {@code nfcIntent}'s NFC properties or {@code null} if the
|
||||
* prerequisites are not met or if an error occurs when reading the NFC properties.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
@SystemApi
|
||||
public Intent createProvisioningIntentFromNfcIntent(@NonNull Intent nfcIntent) {
|
||||
return ProvisioningIntentHelper.createProvisioningIntentFromNfcIntent(nfcIntent);
|
||||
}
|
||||
}
|
||||
|
||||
178
core/java/android/app/admin/ProvisioningIntentHelper.java
Normal file
178
core/java/android/app/admin/ProvisioningIntentHelper.java
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 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_NAME;
|
||||
import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER;
|
||||
import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
|
||||
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_NFC;
|
||||
import static android.nfc.NfcAdapter.EXTRA_NDEF_MESSAGES;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Utility class that provides functionality to create provisioning intents from nfc intents.
|
||||
*/
|
||||
final class ProvisioningIntentHelper {
|
||||
|
||||
private static final String TAG = "ProvisioningIntentHelper";
|
||||
|
||||
/**
|
||||
* This class is never instantiated
|
||||
*/
|
||||
private ProvisioningIntentHelper() { }
|
||||
|
||||
@Nullable
|
||||
public static Intent createProvisioningIntentFromNfcIntent(@NonNull Intent nfcIntent) {
|
||||
requireNonNull(nfcIntent);
|
||||
|
||||
if (!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(nfcIntent.getAction())) {
|
||||
Log.e(TAG, "Wrong Nfc action: " + nfcIntent.getAction());
|
||||
return null;
|
||||
}
|
||||
|
||||
NdefRecord firstRecord = getFirstNdefRecord(nfcIntent);
|
||||
|
||||
if (firstRecord != null) {
|
||||
return createProvisioningIntentFromNdefRecord(firstRecord);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static Intent createProvisioningIntentFromNdefRecord(NdefRecord firstRecord) {
|
||||
requireNonNull(firstRecord);
|
||||
|
||||
Properties properties = loadPropertiesFromPayload(firstRecord.getPayload());
|
||||
|
||||
if (properties == null) {
|
||||
Log.e(TAG, "Failed to load NdefRecord properties.");
|
||||
return null;
|
||||
}
|
||||
|
||||
Bundle bundle = createBundleFromProperties(properties);
|
||||
|
||||
if (!containsRequiredProvisioningExtras(bundle)) {
|
||||
Log.e(TAG, "Bundle does not contain the required provisioning extras.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return createProvisioningIntentFromBundle(bundle);
|
||||
}
|
||||
|
||||
private static Properties loadPropertiesFromPayload(byte[] payload) {
|
||||
Properties properties = new Properties();
|
||||
|
||||
try {
|
||||
properties.load(new StringReader(new String(payload, UTF_8)));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "NFC Intent properties loading failed.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
private static Bundle createBundleFromProperties(Properties properties) {
|
||||
Enumeration propertyNames = properties.propertyNames();
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
while (propertyNames.hasMoreElements()) {
|
||||
String propertyName = (String) propertyNames.nextElement();
|
||||
addPropertyToBundle(propertyName, properties, bundle);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private static void addPropertyToBundle(
|
||||
String propertyName, Properties properties, Bundle bundle) {
|
||||
if(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME.equals(propertyName)) {
|
||||
ComponentName componentName = ComponentName.unflattenFromString(
|
||||
properties.getProperty(propertyName));
|
||||
bundle.putParcelable(propertyName, componentName);
|
||||
}
|
||||
else {
|
||||
bundle.putString(propertyName, properties.getProperty(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
private static Intent createProvisioningIntentFromBundle(Bundle bundle) {
|
||||
requireNonNull(bundle);
|
||||
|
||||
Intent provisioningIntent = new Intent(ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE);
|
||||
|
||||
provisioningIntent.putExtras(bundle);
|
||||
|
||||
provisioningIntent.putExtra(EXTRA_PROVISIONING_TRIGGER, PROVISIONING_TRIGGER_NFC);
|
||||
|
||||
return provisioningIntent;
|
||||
}
|
||||
|
||||
private static boolean containsRequiredProvisioningExtras(Bundle bundle) {
|
||||
return bundle.containsKey(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME) ||
|
||||
bundle.containsKey(EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first {@link NdefRecord} found with a recognized MIME-type
|
||||
*/
|
||||
private static NdefRecord getFirstNdefRecord(Intent nfcIntent) {
|
||||
Parcelable[] ndefMessages = nfcIntent.getParcelableArrayExtra(EXTRA_NDEF_MESSAGES);
|
||||
if (ndefMessages == null) {
|
||||
Log.i(TAG, "No EXTRA_NDEF_MESSAGES from nfcIntent");
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Parcelable rawMsg : ndefMessages) {
|
||||
NdefMessage msg = (NdefMessage) rawMsg;
|
||||
for (NdefRecord record : msg.getRecords()) {
|
||||
String mimeType = new String(record.getType(), UTF_8);
|
||||
|
||||
// Only one first message with NFC_MIME_TYPE is used.
|
||||
if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType)) {
|
||||
return record;
|
||||
}
|
||||
|
||||
// Assume only first record of message is used.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "No compatible records found on nfcIntent");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user