mirror of https://github.com/M66B/FairEmail.git
Watch services/theads
This commit is contained in:
parent
52525cd618
commit
af83f236a3
|
@ -29,6 +29,7 @@ import java.util.List;
|
||||||
|
|
||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.jvm.functions.Function2;
|
import kotlin.jvm.functions.Function2;
|
||||||
|
import leakcanary.AppWatcher;
|
||||||
import leakcanary.LeakCanary;
|
import leakcanary.LeakCanary;
|
||||||
import shark.HeapField;
|
import shark.HeapField;
|
||||||
import shark.HeapObject;
|
import shark.HeapObject;
|
||||||
|
@ -81,6 +82,24 @@ public class CoalMine {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
inspectors.add(new ObjectInspector() {
|
||||||
|
@Override
|
||||||
|
public void inspect(@NonNull ObjectReporter reporter) {
|
||||||
|
String clazz = RunnableEx.class.getName();
|
||||||
|
reporter.whenInstanceOf(clazz, new Function2<ObjectReporter, HeapObject.HeapInstance, Unit>() {
|
||||||
|
@Override
|
||||||
|
public Unit invoke(ObjectReporter reporter, HeapObject.HeapInstance instance) {
|
||||||
|
HeapField fname = instance.get(clazz, "name");
|
||||||
|
if (fname != null) {
|
||||||
|
String name = fname.getValue().readAsJavaString();
|
||||||
|
reporter.getNotLeakingReasons().add("name=" + name);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
LeakCanary.Config config = LeakCanary.getConfig().newBuilder()
|
LeakCanary.Config config = LeakCanary.getConfig().newBuilder()
|
||||||
.dumpHeap(enabled && BuildConfig.DEBUG)
|
.dumpHeap(enabled && BuildConfig.DEBUG)
|
||||||
.objectInspectors(inspectors)
|
.objectInspectors(inspectors)
|
||||||
|
@ -93,8 +112,9 @@ public class CoalMine {
|
||||||
LeakCanary.INSTANCE.dumpHeap();
|
LeakCanary.INSTANCE.dumpHeap();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void watch(Object object, String reason) {
|
static void watch(@NonNull Object object, String reason) {
|
||||||
//AppWatcher.INSTANCE.getObjectWatcher().expectWeaklyReachable(object, reason);
|
Log.i("Watching " + object.getClass() + " because " + reason);
|
||||||
|
AppWatcher.INSTANCE.getObjectWatcher().expectWeaklyReachable(object, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Intent getIntent() {
|
static Intent getIntent() {
|
||||||
|
|
|
@ -5882,6 +5882,7 @@ class Core {
|
||||||
|
|
||||||
void join() {
|
void join() {
|
||||||
join(thread);
|
join(thread);
|
||||||
|
CoalMine.watch(thread, getClass().getSimpleName() + "#join()");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensureRunning(String reason) throws OperationCanceledException {
|
void ensureRunning(String reason) throws OperationCanceledException {
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package eu.faircode.email;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is part of FairEmail.
|
||||||
|
|
||||||
|
FairEmail is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
FairEmail is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Copyright 2018-2022 by Marcel Bokhorst (M66B)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class RunnableEx implements Runnable {
|
||||||
|
public String name;
|
||||||
|
|
||||||
|
public RunnableEx(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
delegate();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.e(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void delegate();
|
||||||
|
}
|
|
@ -67,6 +67,7 @@ public class ServiceExternal extends Service {
|
||||||
Log.i("Service external destroy");
|
Log.i("Service external destroy");
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -131,6 +131,12 @@ public class ServicePowerControl extends ControlsProviderService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
|
}
|
||||||
|
|
||||||
private PendingIntent getPendingIntent() {
|
private PendingIntent getPendingIntent() {
|
||||||
Context context = getBaseContext();
|
Context context = getBaseContext();
|
||||||
return PendingIntentCompat.getActivity(
|
return PendingIntentCompat.getActivity(
|
||||||
|
|
|
@ -191,6 +191,7 @@ public class ServiceSend extends ServiceBase implements SharedPreferences.OnShar
|
||||||
nm.cancel(NotificationHelper.NOTIFICATION_SEND);
|
nm.cancel(NotificationHelper.NOTIFICATION_SEND);
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -430,9 +430,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init(final TupleAccountNetworkState accountNetworkState) {
|
private void init(final TupleAccountNetworkState accountNetworkState) {
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#init") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -473,9 +473,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
"Service start=" + accountNetworkState + " sync=" + sync + " force=" + force);
|
"Service start=" + accountNetworkState + " sync=" + sync + " force=" + force);
|
||||||
|
|
||||||
final Core.State astate = new Core.State(accountNetworkState.networkState);
|
final Core.State astate = new Core.State(accountNetworkState.networkState);
|
||||||
astate.runnable(new Runnable() {
|
astate.runnable(new RunnableEx("state#monitor") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
monitorAccount(accountNetworkState.accountState, astate, sync, force);
|
monitorAccount(accountNetworkState.accountState, astate, sync, force);
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
|
@ -485,9 +485,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
}, "sync.account." + accountNetworkState.accountState.id);
|
}, "sync.account." + accountNetworkState.accountState.id);
|
||||||
coreStates.put(accountNetworkState.accountState.id, astate);
|
coreStates.put(accountNetworkState.accountState.id, astate);
|
||||||
|
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#start") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -522,9 +522,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
EntityLog.log(ServiceSynchronize.this, EntityLog.Type.Scheduling,
|
EntityLog.log(ServiceSynchronize.this, EntityLog.Type.Scheduling,
|
||||||
"Service stop=" + accountNetworkState);
|
"Service stop=" + accountNetworkState);
|
||||||
|
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#stop") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -556,9 +556,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
EntityLog.log(ServiceSynchronize.this, EntityLog.Type.Scheduling,
|
EntityLog.log(ServiceSynchronize.this, EntityLog.Type.Scheduling,
|
||||||
"Service delete=" + accountNetworkState);
|
"Service delete=" + accountNetworkState);
|
||||||
|
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#delete") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -579,9 +579,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
private void quit(final Integer eventId) {
|
private void quit(final Integer eventId) {
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#quit") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -631,12 +631,12 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Runnable backup = new Runnable() {
|
private final Runnable backup = new RunnableEx("state#backup") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
queue.submit(new Runnable() {
|
queue.submit(new RunnableEx("state#backup#exec") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wl.acquire();
|
wl.acquire();
|
||||||
|
|
||||||
|
@ -734,9 +734,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(final List<TupleMessageEx> messages) {
|
public void onChanged(final List<TupleMessageEx> messages) {
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("liveUnseenNotify") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
Core.notifyMessages(ServiceSynchronize.this, messages, notificationData, foreground);
|
Core.notifyMessages(ServiceSynchronize.this, messages, notificationData, foreground);
|
||||||
} catch (SecurityException ex) {
|
} catch (SecurityException ex) {
|
||||||
|
@ -919,6 +919,7 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
nm.cancel(NotificationHelper.NOTIFICATION_SYNCHRONIZE);
|
nm.cancel(NotificationHelper.NOTIFICATION_SYNCHRONIZE);
|
||||||
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1059,9 +1060,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
long id = Long.parseLong(action.split(":")[1]);
|
long id = Long.parseLong(action.split(":")[1]);
|
||||||
|
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("unsnooze") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
EntityFolder folder;
|
EntityFolder folder;
|
||||||
|
|
||||||
|
@ -1178,9 +1179,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
long id = Long.parseLong(action.split(":")[1]);
|
long id = Long.parseLong(action.split(":")[1]);
|
||||||
|
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("exists") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||||
|
|
||||||
|
@ -1214,9 +1215,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPoll(Intent intent) {
|
private void onPoll(Intent intent) {
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("poll") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
DB db = DB.getInstance(ServiceSynchronize.this);
|
DB db = DB.getInstance(ServiceSynchronize.this);
|
||||||
try {
|
try {
|
||||||
|
@ -1758,9 +1759,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
});
|
});
|
||||||
|
|
||||||
// Idle folder
|
// Idle folder
|
||||||
Thread idler = new Thread(new Runnable() {
|
Thread idler = new Thread(new RunnableEx("idle") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
Log.i(folder.name + " start idle");
|
Log.i(folder.name + " start idle");
|
||||||
while (ifolder.isOpen() && state.isRunning() && state.isRecoverable()) {
|
while (ifolder.isOpen() && state.isRunning() && state.isRecoverable()) {
|
||||||
|
@ -1833,12 +1834,12 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
|
|
||||||
forced = true;
|
forced = true;
|
||||||
|
|
||||||
final Runnable purge = new Runnable() {
|
final Runnable purge = new RunnableEx("purge") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("purge#exec") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
wlAccount.acquire();
|
wlAccount.acquire();
|
||||||
|
|
||||||
|
@ -1858,9 +1859,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
final long serial = state.getSerial();
|
final long serial = state.getSerial();
|
||||||
|
|
||||||
Log.i(account.name + " observing operations");
|
Log.i(account.name + " observing operations");
|
||||||
getMainHandler().post(new Runnable() {
|
getMainHandler().post(new RunnableEx("observe#start") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
cowner.value = new TwoStateOwner(ServiceSynchronize.this, account.name);
|
cowner.value = new TwoStateOwner(ServiceSynchronize.this, account.name);
|
||||||
cowner.value.start();
|
cowner.value.start();
|
||||||
|
|
||||||
|
@ -2317,9 +2318,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
Log.i(account.name + " stop watching operations");
|
Log.i(account.name + " stop watching operations");
|
||||||
final TwoStateOwner _owner = cowner.value;
|
final TwoStateOwner _owner = cowner.value;
|
||||||
if (_owner != null)
|
if (_owner != null)
|
||||||
getMainHandler().post(new Runnable() {
|
getMainHandler().post(new RunnableEx("observe#stop") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
_owner.destroy();
|
_owner.destroy();
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
|
@ -2694,9 +2695,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
};
|
};
|
||||||
|
|
||||||
private void updateNetworkState(final Network network, final String reason) {
|
private void updateNetworkState(final Network network, final String reason) {
|
||||||
getMainHandler().post(new Runnable() {
|
getMainHandler().post(new RunnableEx("network") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
Network active = ConnectionHelper.getActiveNetwork(ServiceSynchronize.this);
|
Network active = ConnectionHelper.getActiveNetwork(ServiceSynchronize.this);
|
||||||
|
|
||||||
|
@ -2845,9 +2846,9 @@ public class ServiceSynchronize extends ServiceBase implements SharedPreferences
|
||||||
}
|
}
|
||||||
|
|
||||||
static void boot(final Context context) {
|
static void boot(final Context context) {
|
||||||
executor.submit(new Runnable() {
|
executor.submit(new RunnableEx("boot") {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void delegate() {
|
||||||
try {
|
try {
|
||||||
EntityLog.log(context, "Boot sync service");
|
EntityLog.log(context, "Boot sync service");
|
||||||
|
|
||||||
|
|
|
@ -28,4 +28,10 @@ public class ServiceTileClear extends TileService {
|
||||||
public void onClick() {
|
public void onClick() {
|
||||||
startActivityAndCollapse(ActivityClear.getIntent(this));
|
startActivityAndCollapse(ActivityClear.getIntent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,4 +84,10 @@ public class ServiceTileSynchronize extends TileService implements SharedPrefere
|
||||||
boolean enabled = !prefs.getBoolean("enabled", true);
|
boolean enabled = !prefs.getBoolean("enabled", true);
|
||||||
prefs.edit().putBoolean("enabled", enabled).apply();
|
prefs.edit().putBoolean("enabled", enabled).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ public class ServiceTileUnseen extends TileService {
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
owner.destroy();
|
owner.destroy();
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, getClass().getSimpleName() + "#onDestroy()");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStartListening() {
|
public void onStartListening() {
|
||||||
|
|
|
@ -79,6 +79,7 @@ public class ServiceUI extends IntentService {
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
Log.i("Service UI destroy");
|
Log.i("Service UI destroy");
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
CoalMine.watch(this, "ServiceUI#onDestroy()");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -246,7 +246,6 @@ public abstract class SimpleTask<T> implements LifecycleObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
CoalMine.watch(SimpleTask.this, "Task done=" + name);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,6 @@ public class TwoStateOwner implements LifecycleOwner {
|
||||||
owned = false;
|
owned = false;
|
||||||
destroy();
|
destroy();
|
||||||
owner.getLifecycle().removeObserver(this);
|
owner.getLifecycle().removeObserver(this);
|
||||||
CoalMine.watch(TwoStateOwner.this, "State done=" + aname);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ package eu.faircode.email;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class CoalMine {
|
public class CoalMine {
|
||||||
static void setup(boolean enabled) {
|
static void setup(boolean enabled) {
|
||||||
}
|
}
|
||||||
|
@ -28,7 +30,7 @@ public class CoalMine {
|
||||||
static void check() {
|
static void check() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void watch(Object object, String reason) {
|
static void watch(@NonNull Object object, String reason) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Intent getIntent() {
|
static Intent getIntent() {
|
||||||
|
|
Loading…
Reference in New Issue