diff --git a/TotalCrossSDK/src/main/java/totalcross/sys/Settings.java b/TotalCrossSDK/src/main/java/totalcross/sys/Settings.java index e54ba02df3..5f8cf497f9 100644 --- a/TotalCrossSDK/src/main/java/totalcross/sys/Settings.java +++ b/TotalCrossSDK/src/main/java/totalcross/sys/Settings.java @@ -393,8 +393,6 @@ public static String appBuildNumber() { * In Android 3.0 or greater it will return the serial number; in Android 1.x and 2.x will return * a consistent number that MAY be the same across resets, but has no relation to the real serial number. * - * @see #imei - * @see #iccid * @since SuperWaba 4.21 */ public static String romSerialNumber; @@ -585,25 +583,48 @@ static String initAppPath4D() { */ public static boolean showDesktopMessages = true; - /** Field that represents the smartphone IMEI (if this device is a GSM, UMTS or IDEN smartphone), or null if there's none. + /** + * Field that represents the smartphone IMEI (if this device is a GSM, UMTS or + * IDEN smartphone), or null if there's none. + * * @since TotalCross 1.0 + * @deprecated This field was deprecated and it may be undefined or hold an + * invalid value. */ + @Deprecated public static String imei; - /** Field that represents the smartphone IMEIs; used in phones with more than one line. + /** + * Field that represents the smartphone IMEIs; used in phones with more than one + * line. + * * @since TotalCross 1.0 + * @deprecated This field was deprecated and it may be undefined or hold an + * invalid value. */ + @Deprecated public static String[] imeis; - /** Field that represents the smartphone ESN (if this device is a CDMA smartphone) or null if there's none. + /** + * Field that represents the smartphone ESN (if this device is a CDMA + * smartphone) or null if there's none. + * * @since TotalCross 1.0 + * @deprecated This field was deprecated and it may be undefined or hold an + * invalid value. */ + @Deprecated public static String esn; - /** Field that represents the serial number of the GSM chip or null if there's none. - * Works for Windows Mobile and Android. + /** + * Field that represents the serial number of the GSM chip or null if there's + * none. Works for Windows Mobile and Android. + * * @since TotalCross 1.27 + * @deprecated This field was deprecated and it may be undefined or hold an + * invalid value. */ + @Deprecated public static String iccid; /** If set to true, the application will ignore the event "Close application" issued by the operating system. @@ -919,11 +940,17 @@ public void setRect(int x, int y, int w, int h) @Deprecated public static int windowFont; - /** Returns the line number of the device. Note that if the phone is off it may return null. - * It can be null also if the device uses a non-standard API. Works only on Android, since iOS - * does not allow to get it programatically. For dual-sim devices, returns only the first line number. + /** + * Returns the line number of the device. Note that if the phone is off it may + * return null. It can be null also if the device uses a non-standard API. Works + * only on Android, since iOS does not allow to get it programatically. For + * dual-sim devices, returns only the first line number. + * * @since TotalCross 1.7 / 2.0 + * @deprecated This field was deprecated and it may be undefined or hold an + * invalid value. */ + @Deprecated public static String lineNumber; /** Returns true if the device is currently in landscale (screenWidth > screenHeight). */ diff --git a/TotalCrossSDK/src/main/java/totalcross/telephony/TelephonyManager.java b/TotalCrossSDK/src/main/java/totalcross/telephony/TelephonyManager.java new file mode 100644 index 0000000000..1c404f29f5 --- /dev/null +++ b/TotalCrossSDK/src/main/java/totalcross/telephony/TelephonyManager.java @@ -0,0 +1,68 @@ +// Copyright (C) 2020 TotalCross Global Mobile Platform Ltda. +// +// SPDX-License-Identifier: LGPL-2.1-only + +package totalcross.telephony; + +import com.totalcross.annotations.ReplacedByNativeOnDeploy; + +import totalcross.util.concurrent.Lock; + +public class TelephonyManager { + private static TelephonyManager instance; + + private String[] deviceIds; + private String[] simSerialNumbers; + private String[] lineNumbers; + + private boolean initialized = false; + private Lock initializeLock = new Lock(); + + private TelephonyManager() { + synchronized (initializeLock) { + if (!initialized) { + initialized = nativeInitialize(); + } + } + } + + /** Get the default TelephonyManager. */ + public static TelephonyManager getDefault() { + if (instance == null) { + instance = new TelephonyManager(); + } + return instance; + } + + @ReplacedByNativeOnDeploy + private boolean nativeInitialize() { + return true; + } + + private String getWithIndex(String[] values, int index) { + if (values != null && values.length > index) { + return values[index]; + } + return null; + } + + public String getLine1Number() { + return getWithIndex(lineNumbers, 0); + } + + public String getDeviceId() { + return getWithIndex(deviceIds, 0); + } + + public String getDeviceId(int index) { + return getWithIndex(deviceIds, index); + } + + public String getSimSerialNumber() { + return getWithIndex(simSerialNumbers, 0); + } + + public String getSimSerialNumber(int index) { + return getWithIndex(simSerialNumbers, index); + } +} diff --git a/TotalCrossVM/CMakeLists.txt b/TotalCrossVM/CMakeLists.txt index c960552b01..a5daf0b996 100644 --- a/TotalCrossVM/CMakeLists.txt +++ b/TotalCrossVM/CMakeLists.txt @@ -148,6 +148,7 @@ set(SOURCES ${TC_SRCDIR}/nm/phone/Dial.c ${TC_SRCDIR}/nm/phone/SMS.c ${TC_SRCDIR}/nm/phone/CellInfo.c + ${TC_SRCDIR}/nm/telephony/TelephonyManager.c ${TC_SRCDIR}/nm/telephony/SmsManager.c ${TC_SRCDIR}/nm/firebase/firebase.c diff --git a/TotalCrossVM/android/app/src/main/java/totalcross/android/Settings4A.java b/TotalCrossVM/android/app/src/main/java/totalcross/android/Settings4A.java index 35024bfe05..61f1ecee2f 100644 --- a/TotalCrossVM/android/app/src/main/java/totalcross/android/Settings4A.java +++ b/TotalCrossVM/android/app/src/main/java/totalcross/android/Settings4A.java @@ -147,11 +147,6 @@ static void fillSettings() // userName userName = null; // still looking for a way to retrieve this on droid. - fillTelephonySettings(); - while (!telephonyInitialized) { - try {Thread.sleep(10);} catch (Exception e) {} - } - // if using a new device, get its serial number. otherwise, create one from the mac-address if (romVersion >= 9) // gingerbread try diff --git a/TotalCrossVM/src/init/nativeProcAddressesTC.c b/TotalCrossVM/src/init/nativeProcAddressesTC.c index ccf0db9bf9..ba973436ad 100644 --- a/TotalCrossVM/src/init/nativeProcAddressesTC.c +++ b/TotalCrossVM/src/init/nativeProcAddressesTC.c @@ -549,6 +549,7 @@ void fillNativeProcAddressesTC() htPutPtr(&htNativeProcAddresses, hashCode("tmA_setPositionD_i"), &tmA_setPositionD_i); htPutPtr(&htNativeProcAddresses, hashCode("tmA_setVisibleD_b"), &tmA_setVisibleD_b); htPutPtr(&htNativeProcAddresses, hashCode("tmA_isVisibleD"), &tmA_isVisibleD); + htPutPtr(&htNativeProcAddresses, hashCode("ttTM_nativeInitialize"), &ttTM_nativeInitialize); htPutPtr(&htNativeProcAddresses, hashCode("ttSM_sendTextMessage_sss"), &ttSM_sendTextMessage_sss); htPutPtr(&htNativeProcAddresses, hashCode("ttSM_sendDataMessage_ssiB"), &ttSM_sendDataMessage_ssiB); htPutPtr(&htNativeProcAddresses, hashCode("ttSM_registerSmsReceiver_si"), &ttSM_registerSmsReceiver_si); diff --git a/TotalCrossVM/src/init/posix/settings_c.h b/TotalCrossVM/src/init/posix/settings_c.h index 9a35a7fff2..bab18919b3 100644 --- a/TotalCrossVM/src/init/posix/settings_c.h +++ b/TotalCrossVM/src/init/posix/settings_c.h @@ -270,11 +270,6 @@ void updateDaylightSavings(Context currentContext) bool fillSettings(Context currentContext) { JNIEnv* env = getJNIEnv(); - jmethodID method = (*env)->GetStaticMethodID(env, applicationClass, "requestPhoneStatePermission", "()I"); - jint result = (*env)->CallStaticIntMethod(env, applicationClass, method); - if (result <= 0) { - return false; - } jclass jSettingsClass = androidFindClass(env, "totalcross/android/Settings4A"); jmethodID fillSettingsMethod = (*env)->GetStaticMethodID(env, jSettingsClass, "fillSettings", "()V"); diff --git a/TotalCrossVM/src/nm/NativeMethods.h b/TotalCrossVM/src/nm/NativeMethods.h index 3380172399..4f9660f221 100644 --- a/TotalCrossVM/src/nm/NativeMethods.h +++ b/TotalCrossVM/src/nm/NativeMethods.h @@ -567,6 +567,7 @@ TC_API void tmA_setSizeD_i(NMParams p); TC_API void tmA_setPositionD_i(NMParams p); TC_API void tmA_setVisibleD_b(NMParams p); TC_API void tmA_isVisibleD(NMParams p); +TC_API void ttTM_nativeInitialize(NMParams p); TC_API void ttSM_sendTextMessage_sss(NMParams p); TC_API void ttSM_sendDataMessage_ssiB(NMParams p); TC_API void ttSM_registerSmsReceiver_si(NMParams p); diff --git a/TotalCrossVM/src/nm/NativeMethods.txt b/TotalCrossVM/src/nm/NativeMethods.txt index 7c9727f00e..161b4fe1f4 100644 --- a/TotalCrossVM/src/nm/NativeMethods.txt +++ b/TotalCrossVM/src/nm/NativeMethods.txt @@ -543,6 +543,7 @@ totalcross/money/Ads|native static void setSizeD(int s); totalcross/money/Ads|native static void setPositionD(int p); totalcross/money/Ads|native static void setVisibleD(boolean b); totalcross/money/Ads|native static boolean isVisibleD(); +totalcross/telephony/TelephonyManager|public boolean nativeInitialize(); totalcross/telephony/SmsManager|public native void sendTextMessage(String destinationAddress, String scAddress, String text); totalcross/telephony/SmsManager|public native void sendDataMessage(String destinationAddress, String scAddress, int port, byte []data); totalcross/telephony/SmsManager|public native void registerSmsReceiver(totalcross.telephony.SmsReceiver receiver, int port); diff --git a/TotalCrossVM/src/nm/telephony/TelephonyManager.c b/TotalCrossVM/src/nm/telephony/TelephonyManager.c new file mode 100644 index 0000000000..5f4fa46a3b --- /dev/null +++ b/TotalCrossVM/src/nm/telephony/TelephonyManager.c @@ -0,0 +1,31 @@ +// Copyright (C) 2020 TotalCross Global Mobile Platform Ltda. +// +// SPDX-License-Identifier: LGPL-2.1-only + +#include "TelephonyManager.h" + +#if defined(ANDROID) +#include "android/TelephonyManager_c.h" +#endif + +////////////////////////////////////////////////////////////////////////// +TC_API void ttTM_nativeInitialize(NMParams p) // totalcross/telephony/TelephonyManager public void nativeInitialize(); +{ + TCObject telephonyManager = p->obj[0]; + TCObject* deviceIds = &TelephonyManager_deviceIds(telephonyManager); + TCObject* simSerialNumbers = &TelephonyManager_simSerialNumbers(telephonyManager); + TCObject* lineNumbers = &TelephonyManager_lineNumbers(telephonyManager); + +#if defined (ANDROID) + p->retI = + android_ttTM_nativeInitialize( + p->currentContext, + deviceIds, + simSerialNumbers, + lineNumbers) + == NO_ERROR; +#endif +} +#ifdef ENABLE_TEST_SUITE +//#include "TelephonyManager_test.h" +#endif diff --git a/TotalCrossVM/src/nm/telephony/TelephonyManager.h b/TotalCrossVM/src/nm/telephony/TelephonyManager.h new file mode 100644 index 0000000000..32feab31a3 --- /dev/null +++ b/TotalCrossVM/src/nm/telephony/TelephonyManager.h @@ -0,0 +1,9 @@ +// Copyright (C) 2020 TotalCross Global Mobile Platform Ltda. +// +// SPDX-License-Identifier: LGPL-2.1-only + +#include "tcvm.h" + +#define TelephonyManager_deviceIds(o) FIELD_OBJ(o, OBJ_CLASS(o), 0) +#define TelephonyManager_simSerialNumbers(o) FIELD_OBJ(o, OBJ_CLASS(o), 1) +#define TelephonyManager_lineNumbers(o) FIELD_OBJ(o, OBJ_CLASS(o), 2) diff --git a/TotalCrossVM/src/nm/telephony/android/TelephonyManager_c.h b/TotalCrossVM/src/nm/telephony/android/TelephonyManager_c.h new file mode 100644 index 0000000000..9018f5f8ba --- /dev/null +++ b/TotalCrossVM/src/nm/telephony/android/TelephonyManager_c.h @@ -0,0 +1,67 @@ +// Copyright (C) 2000-2013 SuperWaba Ltda. +// Copyright (C) 2014-2020 TotalCross Global Mobile Platform Ltda. +// +// SPDX-License-Identifier: LGPL-2.1-only + +static TCObject getStaticStringFieldFromClass(JNIEnv* env, Context currentContext, jclass aClass, CharP fieldName) { + char buffer[128]; + jfieldID jfID = (*env)->GetStaticFieldID(env, aClass, fieldName, "Ljava/lang/String;"); + jstring jStringField = (jstring) (*env)->GetStaticObjectField(env, aClass, jfID); + if (jStringField != null) { + jstring2CharP(jStringField, buffer); + (*env)->DeleteLocalRef(env, jStringField); + return createStringObjectFromCharP(currentContext, buffer, -1); + } + return null; +} + +static Err android_ttTM_nativeInitialize(Context currentContext, TCObject* deviceIds, TCObject* simSerialNumbers, TCObject* lineNumbers) { + JNIEnv* env = getJNIEnv(); + jmethodID method = (*env)->GetStaticMethodID(env, applicationClass, "requestPhoneStatePermission", "()I"); + jint result = (*env)->CallStaticIntMethod(env, applicationClass, method); + if (result <= 0) { + return -1; + } + + jclass jSettingsClass = androidFindClass(env, "totalcross/android/Settings4A"); + jmethodID fillTelephonySettings = (*env)->GetStaticMethodID(env, jSettingsClass, "fillTelephonySettings", "()V"); + (*env)->CallStaticVoidMethod(env, jSettingsClass, fillTelephonySettings); + + // deviceIds + (*deviceIds) = createStringArray(currentContext, 2); + if (*deviceIds != null) { + TCObject imeiObj = getStaticStringFieldFromClass(env, currentContext, jSettingsClass, "imei"); + if (imeiObj != null) { + setObjectLock(ARRAYOBJ_GET(*deviceIds, 0) = imeiObj, UNLOCKED); + } + + TCObject imei2Obj = getStaticStringFieldFromClass(env, currentContext, jSettingsClass, "imei2"); + if (imei2Obj != null) { + setObjectLock(ARRAYOBJ_GET(*deviceIds, 1) = imei2Obj, UNLOCKED); + } + setObjectLock((*deviceIds), UNLOCKED); + } + + // simSerialNumbers + (*simSerialNumbers) = createStringArray(currentContext, 1); + if (*simSerialNumbers != null) { + TCObject iccidObj = getStaticStringFieldFromClass(env, currentContext, jSettingsClass, "iccid"); + if (iccidObj != null) { + setObjectLock(ARRAYOBJ_GET(*simSerialNumbers, 0) = iccidObj, UNLOCKED); + } + setObjectLock((*deviceIds), UNLOCKED); + } + + + // phone number - needed to move to here or jni on android 5 will abort + (*lineNumbers) = createStringArray(currentContext, 1); + if (*lineNumbers != null) { + TCObject lineNumberObj = getStaticStringFieldFromClass(env, currentContext, jSettingsClass, "lineNumber"); + if (lineNumberObj != null) { + setObjectLock(ARRAYOBJ_GET(*lineNumbers, 0) = lineNumberObj, UNLOCKED); + } + setObjectLock((*deviceIds), UNLOCKED); + } + + return NO_ERROR; +} diff --git a/TotalCrossVM/src/tcvm/objectmemorymanager.h b/TotalCrossVM/src/tcvm/objectmemorymanager.h index aeae839870..927c543796 100644 --- a/TotalCrossVM/src/tcvm/objectmemorymanager.h +++ b/TotalCrossVM/src/tcvm/objectmemorymanager.h @@ -112,6 +112,8 @@ typedef uint8* Chunk; /// Gets the start of a Java array Object. The array's type is stored in the OBJ_CLASS(o)->name ("[&B","[java.lang.String", etc) #define ARRAYOBJ_START(o) (((uint8*)(o))+TSIZE) +#define ARRAYOBJ_GET(o, i) (*((TCObjectArray) ARRAYOBJ_START(o) + i)) + // Gets the size in bytes of an array. Added to support 64-bit without needing to change tcz structure #define TC_ARRAYSIZE(c, len) (c->flags.isObjectArray ? len * TSIZE : len << c->flags.bits2shift)