1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.snippet.bluetooth; 18 19 import android.app.UiAutomation; 20 import android.bluetooth.BluetoothDevice; 21 import android.bluetooth.OobData; 22 23 import androidx.test.platform.app.InstrumentationRegistry; 24 25 import org.json.JSONArray; 26 import org.json.JSONException; 27 import org.json.JSONObject; 28 29 import java.lang.reflect.Method; 30 import java.util.List; 31 32 public class Utils { Utils()33 private Utils() {} 34 adoptShellPermission()35 public static void adoptShellPermission() { 36 UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 37 uia.adoptShellPermissionIdentity(); 38 // Need to drop the UI Automation to allow other snippets to get access 39 // to global UI automation. 40 // Using reflection here since the method is not public. 41 try { 42 Class<?> cls = Class.forName("android.app.UiAutomation"); 43 Method destroyMethod = cls.getDeclaredMethod("destroy"); 44 destroyMethod.invoke(uia); 45 } catch (ReflectiveOperationException e) { 46 throw new IllegalStateException("Failed to cleaup Ui Automation", e); 47 } 48 } 49 dropShellPermission()50 public static void dropShellPermission() { 51 UiAutomation uia = InstrumentationRegistry.getInstrumentation().getUiAutomation(); 52 uia.dropShellPermissionIdentity(); 53 // Need to drop the UI Automation to allow other snippets to get access 54 // to global UI automation. 55 // Using reflection here since the method is not public. 56 try { 57 Class<?> cls = Class.forName("android.app.UiAutomation"); 58 Method destroyMethod = cls.getDeclaredMethod("destroy"); 59 destroyMethod.invoke(uia); 60 } catch (ReflectiveOperationException e) { 61 throw new IllegalStateException("Failed to cleaup Ui Automation", e); 62 } 63 } 64 convertJSONArrayToByteArray(JSONArray jArray)65 private static byte[] convertJSONArrayToByteArray(JSONArray jArray) throws JSONException { 66 if (jArray == null) { 67 return null; 68 } 69 byte[] bArray = new byte[jArray.length()]; 70 for (int i = 0; i < jArray.length(); i++) { 71 bArray[i] = (byte) jArray.getInt(i); 72 } 73 return bArray; 74 } 75 convertByteArrayToJSONArray(byte[] array)76 private static JSONArray convertByteArrayToJSONArray(byte[] array) throws JSONException { 77 if (array == null) { 78 return null; 79 } 80 return new JSONArray(array); 81 } 82 convertOobDataToJson(OobData oobData)83 public static JSONObject convertOobDataToJson(OobData oobData) throws JSONException { 84 if (oobData == null) return null; 85 return new JSONObject() 86 .put("device_address_with_type", 87 convertByteArrayToJSONArray(oobData.getDeviceAddressWithType())) 88 .put("confirmation_hash", 89 convertByteArrayToJSONArray(oobData.getConfirmationHash())) 90 .put("randomizer_hash", 91 convertByteArrayToJSONArray(oobData.getRandomizerHash())) 92 .put("device_name", convertByteArrayToJSONArray(oobData.getDeviceName())) 93 .put("classic_length", 94 convertByteArrayToJSONArray(oobData.getClassicLength())) 95 .put("class_of_device", 96 convertByteArrayToJSONArray(oobData.getClassOfDevice())) 97 .put("le_temporary_key", 98 convertByteArrayToJSONArray(oobData.getLeTemporaryKey())) 99 .put("le_temporary_appearance", 100 convertByteArrayToJSONArray(oobData.getLeAppearance())) 101 .put("le_flags", oobData.getLeFlags()) 102 .put("le_device_role", oobData.getLeDeviceRole()); 103 } 104 convertJsonToOobData(JSONObject jsonObj)105 public static OobData convertJsonToOobData(JSONObject jsonObj) throws JSONException { 106 if (jsonObj == null) return null; 107 return new OobData.LeBuilder( 108 convertJSONArrayToByteArray( 109 jsonObj.getJSONArray("confirmation_hash")), 110 convertJSONArrayToByteArray( 111 jsonObj.getJSONArray("device_address_with_type")), 112 jsonObj.getInt("le_device_role")) 113 .setLeTemporaryKey(convertJSONArrayToByteArray( 114 jsonObj.getJSONArray("le_temporary_key"))) 115 .setRandomizerHash(convertJSONArrayToByteArray( 116 jsonObj.getJSONArray("randomizer_hash"))) 117 .setLeFlags(jsonObj.getInt("le_flags")) 118 .setDeviceName(convertJSONArrayToByteArray( 119 jsonObj.getJSONArray("device_name"))) 120 .build(); 121 } 122 convertBtDeviceToJson(BluetoothDevice btDevice)123 public static String convertBtDeviceToJson(BluetoothDevice btDevice) throws JSONException { 124 if (btDevice == null) return null; 125 return btDevice.getAddress(); 126 } 127 convertBtDevicesToJson(List<BluetoothDevice> btDevices)128 public static JSONArray convertBtDevicesToJson(List<BluetoothDevice> btDevices) throws JSONException { 129 if (btDevices == null) return null; 130 JSONArray jsonArray = new JSONArray(); 131 for (BluetoothDevice device: btDevices) { 132 jsonArray.put(device.getAddress()); 133 } 134 return jsonArray; 135 } 136 } 137