- Fix an issue when the permission to read the KML folder has been lost.

- Remove unused win32 timer source code.
This commit is contained in:
dgis 2020-12-09 00:43:01 +01:00
parent efc2139026
commit 100e6ef24e
7 changed files with 36 additions and 142 deletions

View file

@ -63,9 +63,10 @@ LINKS
CHANGES
Version 2.2 (2020-12-08)
Version 2.2 (2020-12-09)
- The KML folder is now saved when changing the KML script for a custom one via the menu "Change KML Script...".
- The KML folder is now well saved when changing the KML script for a custom one via the menu "Change KML Script...".
- Fix an issue when the permission to read the KML folder has been lost.
Version 2.1 (2020-11-23)

View file

@ -19,7 +19,6 @@ cmake_minimum_required(VERSION 3.4.1)
#add_compile_options(-DDEBUG_ANDROID_FILE)
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
#add_compile_options(-DWIN32_TIMER_THREAD) # old timer algorithm which stop when no more thread!
add_compile_options(-DEMUXX=48)

View file

@ -33,8 +33,8 @@ android {
applicationId "org.emulator.forty.eight"
minSdkVersion 19
targetSdkVersion 29
versionCode 18
versionName "2.1"
versionCode 20
versionName "2.2"
setProperty("archivesBaseName", "Emu48-v$versionName")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {

View file

@ -63,9 +63,10 @@ LINKS
CHANGES
Version 2.2 (2020-12-08)
Version 2.2 (2020-12-09)
- The KML folder is now saved when changing the KML script for a custom one via the menu "Change KML Script...".
- The KML folder is now well saved when changing the KML script for a custom one via the menu "Change KML Script...".
- Fix an issue when the permission to read the KML folder has been lost.
Version 2.1 (2020-11-23)

View file

@ -2498,128 +2498,6 @@ HANDLE WINAPI GetClipboardData(UINT uFormat) {
return szText;
}
#if defined WIN32_TIMER_THREAD
struct timerEvent {
BOOL valid;
int timerId;
LPTIMECALLBACK fptc;
DWORD_PTR dwUser;
UINT fuEvent;
timer_t timer;
};
#define MAX_TIMER 10
struct timerEvent timerEvents[MAX_TIMER];
pthread_mutex_t timerEventsLock;
static void initTimer() {
for (int i = 0; i < MAX_TIMER; ++i) {
timerEvents[i].valid = FALSE;
}
}
void deleteTimeEvent(UINT uTimerID) {
pthread_mutex_lock(&timerEventsLock);
timer_delete(timerEvents[uTimerID - 1].timer);
timerEvents[uTimerID - 1].valid = FALSE;
pthread_mutex_unlock(&timerEventsLock);
}
MMRESULT timeKillEvent(UINT uTimerID) {
TIMER_LOGD("timeKillEvent(uTimerID: [%d])", uTimerID);
deleteTimeEvent(uTimerID);
return 0; //No error
}
void timerCallback(int timerId) {
if(timerId >= 0 && timerId < MAX_TIMER && timerEvents[timerId].valid) {
timerEvents[timerId].fptc((UINT) (timerId + 1), 0, (DWORD) timerEvents[timerId].dwUser, 0, 0);
if(timerEvents[timerId].fuEvent == TIME_ONESHOT) {
TIMER_LOGD("timerCallback remove timer uTimerID [%d]", timerId + 1);
deleteTimeEvent((UINT) (timerId + 1));
}
jniDetachCurrentThread();
}
}
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
TIMER_LOGD("timeSetEvent(uDelay: %d, fuEvent: %d)", uDelay, fuEvent);
pthread_mutex_lock(&timerEventsLock);
// Find a timer id
int timerId = -1;
for (int i = 0; i < MAX_TIMER; ++i) {
if(!timerEvents[i].valid) {
timerId = i;
break;
}
}
if(timerId == -1) {
LOGD("timeSetEvent() ERROR: No more timer available");
pthread_mutex_unlock(&timerEventsLock);
return NULL;
}
timerEvents[timerId].timerId = timerId;
timerEvents[timerId].fptc = fptc;
timerEvents[timerId].dwUser = dwUser;
timerEvents[timerId].fuEvent = fuEvent;
struct sigevent sev;
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = (void (*)(sigval_t)) timerCallback; //this function will be called when timer expires
sev.sigev_value.sival_int = timerEvents[timerId].timerId; //this argument will be passed to cbf
sev.sigev_notify_attributes = NULL;
timer_t * timer = &(timerEvents[timerId].timer);
// CLOCK_REALTIME 0 OK but X intervals only
// CLOCK_MONOTONIC 1 OK but X intervals only
// CLOCK_PROCESS_CPUTIME_ID 2 NOTOK, not working with PERIODIC!
// CLOCK_THREAD_CPUTIME_ID 3 NOTOK
// CLOCK_MONOTONIC_RAW 4 NOTOK
// CLOCK_REALTIME_COARSE 5 NOTOK
// CLOCK_MONOTONIC_COARSE 6 NOTOK
// CLOCK_BOOTTIME 7 OK but X intervals only
// CLOCK_REALTIME_ALARM 8 NOTOK EPERM
// CLOCK_BOOTTIME_ALARM 9 NOTOK EPERM
// CLOCK_SGI_CYCLE 10 NOTOK EINVAL
// CLOCK_TAI 11
if (timer_create(CLOCK_REALTIME, &sev, timer) == -1) {
LOGD("timeSetEvent() ERROR in timer_create, errno: %d (EAGAIN 11 / EINVAL 22 / ENOMEM 12)", errno);
// EAGAIN Temporary error during kernel allocation of timer structures.
// EINVAL Clock ID, sigev_notify, sigev_signo, or sigev_notify_thread_id is invalid.
// ENOMEM Could not allocate memory.
pthread_mutex_unlock(&timerEventsLock);
return NULL;
}
long freq_nanosecs = uDelay;
struct itimerspec its;
its.it_value.tv_sec = freq_nanosecs / 1000;
its.it_value.tv_nsec = (freq_nanosecs % 1000) * 1000000;
if(fuEvent == TIME_PERIODIC) {
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
} else /*if(fuEvent == TIME_ONESHOT)*/ {
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
}
if (timer_settime(timerEvents[timerId].timer, 0, &its, NULL) == -1) {
LOGD("timeSetEvent() ERROR in timer_settime, errno: %d (EFAULT 14 / EINVAL 22)", errno);
// EFAULT new_value, old_value, or curr_value is not a valid pointer.
// EINVAL timerid is invalid. Or new_value.it_value is negative; or new_value.it_value.tv_nsec is negative or greater than 999,999,999.
timer_delete(timerEvents[timerId].timer);
pthread_mutex_unlock(&timerEventsLock);
return NULL;
}
timerEvents[timerId].valid = TRUE;
TIMER_LOGD("timeSetEvent() -> timerId+1: [%d]", timerId + 1);
pthread_mutex_unlock(&timerEventsLock);
return (MMRESULT) (timerId + 1); // No error
}
#else
struct timerEvent {
int timerId;
UINT uDelay;
@ -2707,7 +2585,7 @@ static void insertTimer(struct timerEvent * newTimer) {
}
static void timerThreadStart(LPVOID lpThreadParameter) {
LOGD("timerThreadStart() START");
TIMER_LOGD("timerThreadStart() START");
pthread_mutex_lock(&timerEventsLock);
while (!timerThreadToEnd) {
TIMER_LOGD("timerThreadStart() %ld", GetTickCount64());
@ -2768,7 +2646,7 @@ static void timerThreadStart(LPVOID lpThreadParameter) {
timerThreadId = 0;
pthread_mutex_unlock(&timerEventsLock);
jniDetachCurrentThread();
LOGD("timerThreadStart() END");
TIMER_LOGD("timerThreadStart() END");
}
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
@ -2793,9 +2671,9 @@ MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_
if(!timerThreadId) {
// If not yet created, create the thread which will handle all the timers
LOGD("timeSetEvent() pthread_create");
TIMER_LOGD("timeSetEvent() pthread_create");
if (pthread_create(&timerThreadId, NULL, (void *(*)(void *)) timerThreadStart, NULL) != 0) {
LOGD("timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", errno);
TIMER_LOGD("timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", errno);
// EAGAIN Insufficient resources to create another thread.
// EINVAL Invalid settings in attr.
// ENOMEM No permission to set the scheduling policy and parameters specified in attr.
@ -2808,7 +2686,6 @@ MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_
pthread_mutex_unlock(&timerEventsLock);
return (MMRESULT) newTimer->timerId; // No error
}
#endif
MMRESULT timeGetDevCaps(LPTIMECAPS ptc, UINT cbtc) {
if(ptc) {

View file

@ -994,7 +994,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
// We only change the KML script here.
int result = NativeLib.onViewScript(scriptItem.filename, scriptItem.folder);
if(result > 0) {
//TODO no need to call changeKMLFolder(scriptItem.folder);
settings.putString("settings_kml_folder_embedded", scriptItem.folder);
displayKMLTitle();
showKMLLog();
@ -1515,8 +1514,20 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
// Change the default KMLFolder to allow getFirstKMLFilenameForType() to find in the specific folder!
Uri kmlFolderUri = Uri.parse(kmlScriptFolder);
DocumentFile kmlFolderDocumentFile = DocumentFile.fromTreeUri(this, kmlFolderUri);
if(kmlFolderDocumentFile != null && kmlFolderDocumentFile.exists())
if(kmlFolderDocumentFile != null) {
// Check the permission of the folder kmlScriptFolder
if (!kmlFolderDocumentFile.canRead()) {
// Permission denied, switch to the default asset folder
changeKMLFolder(null);
kmlScriptFolder = null;
showAlert(getString(R.string.message_open_kml_folder_permission_lost), true);
} else if (kmlFolderDocumentFile.exists())
changeKMLFolder(kmlScriptFolder);
} else {
// We are using the API < 21, so we
changeKMLFolder(null);
kmlScriptFolder = null;
}
}
if(settings.getBoolean("settings_port2en", false)) {
@ -1527,13 +1538,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
DocumentFile port2DocumentFile = DocumentFile.fromSingleUri(this, port2Uri);
if (port2DocumentFile == null || !port2DocumentFile.exists()) {
String port2Filename = getFilenameFromURL(port2Url);
String finalKmlScriptFolder = kmlScriptFolder;
new AlertDialog.Builder(this)
.setTitle(getString(R.string.message_open_port2_file_not_found))
.setMessage(String.format(Locale.US, getString(R.string.message_open_port2_file_not_found_description), port2Filename))
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
urlToOpenInIntentPort2Load = url;
kmlScriptFolderInIntentPort2Load = kmlScriptFolder;
kmlScriptFolderInIntentPort2Load = finalKmlScriptFolder;
Intent intentPort2 = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intentPort2.addCategory(Intent.CATEGORY_OPENABLE);
@ -1544,7 +1556,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}).setNegativeButton(android.R.string.cancel, (dialog, which) -> {
// Deactivate the port2 because it is not reachable.
settings.putBoolean("settings_port2en", false);
onFileOpenNative(url, kmlScriptFolder);
onFileOpenNative(url, finalKmlScriptFolder);
}).show();
return;
}
@ -1936,7 +1948,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
for (int i = 0; i < kmlScripts.size(); i++) {
KMLScriptItem kmlScriptItem = kmlScripts.get(i);
if (kmlScriptItem.model.charAt(0) == chipsetType) {
showAlert(String.format(Locale.US, "Existing KML script not found. Trying the compatible script: %s", kmlScriptItem.filename), true);
showAlert(String.format(Locale.US, getString(R.string.message_open_kml_not_found_alert_trying_other1), kmlScriptItem.filename), true);
NativeLib.setCurrentKml(kmlScriptItem.filename);
NativeLib.setEmuDirectory(kmlFolderURL);
return 1;
@ -1953,13 +1965,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
for (int i = 0; i < kmlScripts.size(); i++) {
KMLScriptItem kmlScriptItem = kmlScripts.get(i);
if (kmlScriptItem.model.charAt(0) == chipsetType) {
showAlert(String.format(Locale.US, "Existing KML script not found. Trying the embedded and compatible script: %s", kmlScriptItem.filename), true);
showAlert(String.format(Locale.US, getString(R.string.message_open_kml_not_found_alert_trying_other2), kmlScriptItem.filename), true);
NativeLib.setCurrentKml(kmlScriptItem.filename);
NativeLib.setEmuDirectory("assets/calculators/");
return 1;
}
}
showAlert("Cannot find the KML template file, sorry.", true);
showAlert(getString(R.string.message_open_kml_not_found_alert), true);
return 0;
}

View file

@ -93,10 +93,14 @@
<string name="message_open_security_description">For security reason, you must select the folder where are the KML and ROM files, please.</string>
<string name="message_open_security_retry">Please, open again</string>
<string name="message_open_security_retry_description">I hope now you could open again the state file.</string>
<string name="message_open_kml_folder_permission_lost">Permission denied to access to the previously saved KML folder. Switch to the default embedded KML folder.</string>
<string name="message_open_kml_not_found">KML Script not Found</string>
<string name="message_open_kml_not_found_description">You must select the folder where are the KML and ROM files, please.</string>
<string name="message_open_kml_not_found_description2">The KML script "%s" cannot be found. You must select the folder where are the KML and ROM files, please.</string>
<string name="message_open_kml_not_found_description3">The KML script "%s" cannot be found in the folder "%s". You must select the folder where are the KML and ROM files, please.</string>
<string name="message_open_kml_not_found_alert_trying_other1">Existing KML script not found. Trying the compatible script: %s</string>
<string name="message_open_kml_not_found_alert_trying_other2">"Existing KML script not found. Trying the embedded and compatible script: %s"</string>
<string name="message_open_kml_not_found_alert">"Cannot find the KML template file, sorry."</string>
<string name="message_open_port2_file_not_found">Port 2 File not Found</string>
<string name="message_open_port2_file_not_found_description">The port 2 file "%s" cannot be found. You should select it again, please.</string>
<string name="message_state_saved">State saved in %s</string>