diff options
author | roldenburg <roldenburg@google.com> | 2018-02-22 23:37:42 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-02-22 23:37:42 +0000 |
commit | a86d75663a3f95e56ddff9ae232c71abf7fd7702 (patch) | |
tree | 7137845d46c352956c7b9f802e0afc5a053f8541 | |
parent | 02b68180bdd37434fa8c0c7f8cb052ae6bd3ecad (diff) | |
parent | 26c4466796997d2af5140eea89331c2c5f7c1868 (diff) |
Merge "Show IMEI/MEID in hex, dec, and barcode when appropriate" am: 494552349a am: 4d2b250192
am: 26c4466796
Change-Id: I756e5b2ec75667aedf4fb021b706ac1b1dcc6d36
7 files changed, 238 insertions, 9 deletions
diff --git a/Android.mk b/Android.mk index 7f165f279..4059ca08f 100644 --- a/Android.mk +++ b/Android.mk @@ -116,6 +116,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \ dialer-guava-target \ dialer-glide-target \ dialer-glide-annotation-target \ + dialer-zxing-target \ jsr305 \ libbackup \ libphonenumber \ @@ -413,3 +414,14 @@ LOCAL_UNINSTALLABLE_MODULE := true include $(BUILD_PREBUILT) include $(CLEAR_VARS) + +LOCAL_MODULE_CLASS := JAVA_LIBRARIES +LOCAL_MODULE := dialer-zxing-target +LOCAL_SDK_VERSION := current +LOCAL_SRC_FILES := ../../../external/zxing/core/core.jar +LOCAL_UNINSTALLABLE_MODULE := true + +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) + diff --git a/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java b/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java index 2b7209eb5..c349d2235 100644 --- a/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java +++ b/java/com/android/dialer/dialpadview/SpecialCharSequenceMgr.java @@ -17,6 +17,7 @@ package com.android.dialer.dialpadview; import android.Manifest; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.app.DialogFragment; @@ -28,6 +29,9 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Color; import android.net.Uri; import android.provider.Settings; import android.support.annotation.Nullable; @@ -37,8 +41,15 @@ import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; +import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager; import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; import android.widget.Toast; import com.android.common.io.MoreCloseables; import com.android.contacts.common.database.NoNullCursorAsyncQueryHandler; @@ -51,8 +62,14 @@ import com.android.dialer.compat.telephony.TelephonyManagerCompat; import com.android.dialer.oem.MotorolaUtils; import com.android.dialer.telecom.TelecomUtil; import com.android.dialer.util.PermissionsUtil; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Locale; /** * Helper class to listen for some magic character sequences that are handled specially by the @@ -66,12 +83,9 @@ import java.util.List; * shared library?) */ public class SpecialCharSequenceMgr { - - private static final String TAG = "SpecialCharSequenceMgr"; - private static final String TAG_SELECT_ACCT_FRAGMENT = "tag_select_acct_fragment"; - private static final String MMI_IMEI_DISPLAY = "*#06#"; + @VisibleForTesting static final String MMI_IMEI_DISPLAY = "*#06#"; private static final String MMI_REGULATORY_INFO_DISPLAY = "*#07#"; /** ***** This code is used to handle SIM Contact queries ***** */ private static final String ADN_PHONE_NUMBER_COLUMN_NAME = "number"; @@ -306,6 +320,7 @@ public class SpecialCharSequenceMgr { // TODO: Use TelephonyCapabilities.getDeviceIdLabel() to get the device id label instead of a // hard-coded string. + @SuppressLint("HardwareIds") static boolean handleDeviceIdDisplay(Context context, String input) { if (!PermissionsUtil.hasPermission(context, Manifest.permission.READ_PHONE_STATE)) { return false; @@ -319,29 +334,143 @@ public class SpecialCharSequenceMgr { ? R.string.imei : R.string.meid; - List<String> deviceIds = new ArrayList<String>(); + View customView = LayoutInflater.from(context).inflate(R.layout.dialog_deviceids, null); + ViewGroup holder = customView.findViewById(R.id.deviceids_holder); + if (TelephonyManagerCompat.getPhoneCount(telephonyManager) > 1) { for (int slot = 0; slot < telephonyManager.getPhoneCount(); slot++) { String deviceId = telephonyManager.getDeviceId(slot); if (!TextUtils.isEmpty(deviceId)) { - deviceIds.add(deviceId); + addDeviceIdRow(holder, deviceId, /* showBarcode */ false); } } } else { - deviceIds.add(telephonyManager.getDeviceId()); + addDeviceIdRow(holder, telephonyManager.getDeviceId(), /* showBarcode */ true); } new AlertDialog.Builder(context) .setTitle(labelResId) - .setItems(deviceIds.toArray(new String[deviceIds.size()]), null) + .setView(customView) .setPositiveButton(android.R.string.ok, null) .setCancelable(false) - .show(); + .show() + .getWindow() + .setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); return true; } return false; } + private static void addDeviceIdRow(ViewGroup holder, String deviceId, boolean showBarcode) { + if (TextUtils.isEmpty(deviceId)) { + return; + } + + ViewGroup row = + (ViewGroup) + LayoutInflater.from(holder.getContext()).inflate(R.layout.row_deviceid, holder, false); + holder.addView(row); + + // Remove the check digit, if exists. This digit is a checksum of the ID. + // See https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity + // and https://en.wikipedia.org/wiki/Mobile_equipment_identifier + String hex = deviceId.length() == 15 ? deviceId.substring(0, 14) : deviceId; + + // If this is the valid length IMEI or MEID (14 digits), show it in all formats, otherwise fall + // back to just showing the raw hex + if (hex.length() == 14) { + ((TextView) row.findViewById(R.id.deviceid_hex)).setText(hex); + ((TextView) row.findViewById(R.id.deviceid_dec)).setText(getDecimalFromHex(hex)); + row.findViewById(R.id.deviceid_dec_label).setVisibility(View.VISIBLE); + } else { + ((TextView) row.findViewById(R.id.deviceid_hex)).setText(deviceId); + } + + final ImageView barcode = row.findViewById(R.id.deviceid_barcode); + if (showBarcode) { + // Wait until the layout pass has completed so we the barcode is measured before drawing. We + // do this by adding a layout listener and setting the bitmap after getting the callback. + barcode + .getViewTreeObserver() + .addOnGlobalLayoutListener( + new OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + barcode.getViewTreeObserver().removeOnGlobalLayoutListener(this); + Bitmap barcodeBitmap = + generateBarcode(hex, barcode.getWidth(), barcode.getHeight()); + if (barcodeBitmap != null) { + barcode.setImageBitmap(barcodeBitmap); + } + } + }); + } else { + barcode.setVisibility(View.GONE); + } + } + + private static String getDecimalFromHex(String hex) { + final String part1 = hex.substring(0, 8); + final String part2 = hex.substring(8); + + long dec1; + try { + dec1 = Long.parseLong(part1, 16); + } catch (NumberFormatException e) { + LogUtil.e("SpecialCharSequenceMgr.getDecimalFromHex", "unable to parse hex", e); + return ""; + } + + final String manufacturerCode = String.format(Locale.US, "%010d", dec1); + + long dec2; + try { + dec2 = Long.parseLong(part2, 16); + } catch (NumberFormatException e) { + LogUtil.e("SpecialCharSequenceMgr.getDecimalFromHex", "unable to parse hex", e); + return ""; + } + + final String serialNum = String.format(Locale.US, "%08d", dec2); + + StringBuilder builder = new StringBuilder(22); + builder + .append(manufacturerCode, 0, 5) + .append(' ') + .append(manufacturerCode, 5, manufacturerCode.length()) + .append(' ') + .append(serialNum, 0, 4) + .append(' ') + .append(serialNum, 4, serialNum.length()); + return builder.toString(); + } + + /** + * This method generates a 2d barcode using the zxing library. Each pixel of the bitmap is either + * black or white painted vertically. We determine which color using the BitMatrix.get(x, y) + * method. + */ + private static Bitmap generateBarcode(String hex, int width, int height) { + MultiFormatWriter writer = new MultiFormatWriter(); + String data = Uri.encode(hex); + + try { + BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.CODE_128, width, 1); + Bitmap bitmap = Bitmap.createBitmap(bitMatrix.getWidth(), height, Config.RGB_565); + + for (int i = 0; i < bitMatrix.getWidth(); i++) { + // Paint columns of width 1 + int[] column = new int[height]; + Arrays.fill(column, bitMatrix.get(i, 0) ? Color.BLACK : Color.WHITE); + bitmap.setPixels(column, 0, 1, i, 0, 1, height); + } + return bitmap; + } catch (WriterException e) { + LogUtil.e("SpecialCharSequenceMgr.generateBarcode", "error generating barcode", e); + } + return null; + } + private static boolean handleRegulatoryInfoDisplay(Context context, String input) { if (input.equals(MMI_REGULATORY_INFO_DISPLAY)) { LogUtil.i( diff --git a/java/com/android/dialer/dialpadview/res/layout/dialog_deviceids.xml b/java/com/android/dialer/dialpadview/res/layout/dialog_deviceids.xml new file mode 100644 index 000000000..89e256bde --- /dev/null +++ b/java/com/android/dialer/dialpadview/res/layout/dialog_deviceids.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 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. +--> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:id="@+id/deviceids_holder" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingStart="?dialogPreferredPadding" + android:paddingEnd="?dialogPreferredPadding" + android:orientation="vertical"/> +</ScrollView> diff --git a/java/com/android/dialer/dialpadview/res/layout/row_deviceid.xml b/java/com/android/dialer/dialpadview/res/layout/row_deviceid.xml new file mode 100644 index 000000000..53f3e5d0d --- /dev/null +++ b/java/com/android/dialer/dialpadview/res/layout/row_deviceid.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2018 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. +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="?dialogPreferredPadding" + android:orientation="vertical"> + <TextView + style="@style/DeviceIdBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/hex"/> + <TextView + android:id="@+id/deviceid_hex" + style="@style/DeviceIdBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <TextView + android:id="@+id/deviceid_dec_label" + style="@style/DeviceIdBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/dec" + android:visibility="gone"/> + <TextView + android:id="@+id/deviceid_dec" + style="@style/DeviceIdBody" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + <ImageView + android:id="@+id/deviceid_barcode" + android:layout_width="match_parent" + android:layout_height="@dimen/barcode_height" + android:layout_margin="24dp" + android:layout_gravity="center_horizontal"/> +</LinearLayout> diff --git a/java/com/android/dialer/dialpadview/res/values/dimens.xml b/java/com/android/dialer/dialpadview/res/values/dimens.xml index 4b386eeb5..6892fcf30 100644 --- a/java/com/android/dialer/dialpadview/res/values/dimens.xml +++ b/java/com/android/dialer/dialpadview/res/values/dimens.xml @@ -43,4 +43,6 @@ <!-- Length of dialpad's shadows in dialer. --> <dimen name="shadow_length">10dp</dimen> + + <dimen name="barcode_height">100dp</dimen> </resources> diff --git a/java/com/android/dialer/dialpadview/res/values/strings.xml b/java/com/android/dialer/dialpadview/res/values/strings.xml index 094ca6b8f..51367b644 100644 --- a/java/com/android/dialer/dialpadview/res/values/strings.xml +++ b/java/com/android/dialer/dialpadview/res/values/strings.xml @@ -77,6 +77,12 @@ <!-- The title of a dialog that displays the MEID of the CDMA phone --> <string name="meid">MEID</string> + <!-- The label for the hex encoding of the device ID --> + <string name="hex" translatable="false">HEX:</string> + + <!-- The label for the decimal encoding of the device ID --> + <string name="dec" translatable="false">DEC:</string> + <!-- Dialog text displayed when loading a phone number from the SIM card for speed dial --> <string name="simContacts_emptyLoading">Loading from SIM card\u2026</string> diff --git a/java/com/android/dialer/dialpadview/res/values/styles.xml b/java/com/android/dialer/dialpadview/res/values/styles.xml index d69e6a832..75a54a305 100644 --- a/java/com/android/dialer/dialpadview/res/values/styles.xml +++ b/java/com/android/dialer/dialpadview/res/values/styles.xml @@ -116,4 +116,9 @@ <item name="dialpad_voicemail_tint">?attr/dialpad_text_color_secondary</item> <item name="dialpad_background">#00000000</item> </style> + + <style name="DeviceIdBody"> + <item name="android:textColor">?android:textColorPrimary</item> + <item name="android:textSize">16sp</item> + </style> </resources> |