Watch services/theads

This commit is contained in:
M66B 2022-04-17 21:34:33 +02:00
parent 52525cd618
commit af83f236a3
14 changed files with 126 additions and 43 deletions

View File

@ -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() {

View File

@ -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 {

View File

@ -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();
}

View File

@ -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

View File

@ -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(

View File

@ -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

View File

@ -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");

View File

@ -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()");
}
} }

View File

@ -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()");
}
} }

View File

@ -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() {

View File

@ -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

View File

@ -246,7 +246,6 @@ public abstract class SimpleTask<T> implements LifecycleObserver {
} }
} }
}); });
CoalMine.watch(SimpleTask.this, "Task done=" + name);
} }
}); });

View File

@ -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);
} }
}); });
} }

View File

@ -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() {