2018-12-24 12:27:45 +00:00
package eu.faircode.email ;
2018-12-31 08:04:33 +00:00
/ *
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/>.
2023-01-01 07:52:55 +00:00
Copyright 2018 - 2023 by Marcel Bokhorst ( M66B )
2018-12-31 08:04:33 +00:00
* /
2023-04-02 08:28:54 +00:00
import static androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION ;
2023-06-03 18:56:52 +00:00
import android.Manifest ;
2019-07-22 07:18:03 +00:00
import android.app.ActivityManager ;
2020-07-11 13:09:32 +00:00
import android.app.ApplicationExitInfo ;
2019-12-06 07:50:46 +00:00
import android.app.Dialog ;
2021-09-27 14:57:17 +00:00
import android.app.Notification ;
2020-10-09 12:29:30 +00:00
import android.app.NotificationChannel ;
import android.app.NotificationManager ;
2022-01-31 12:36:19 +00:00
import android.app.usage.UsageEvents ;
2019-05-12 17:14:34 +00:00
import android.app.usage.UsageStatsManager ;
2023-06-15 20:37:26 +00:00
import android.content.ComponentName ;
2021-08-23 16:03:34 +00:00
import android.content.ContentResolver ;
2019-05-12 17:14:34 +00:00
import android.content.Context ;
2019-12-06 07:50:46 +00:00
import android.content.DialogInterface ;
2019-01-25 14:40:46 +00:00
import android.content.Intent ;
2019-05-12 17:14:34 +00:00
import android.content.SharedPreferences ;
2023-01-18 07:44:45 +00:00
import android.content.UriPermission ;
2022-06-18 10:18:35 +00:00
import android.content.pm.ApplicationInfo ;
2021-02-10 17:24:45 +00:00
import android.content.pm.PackageInfo ;
import android.content.pm.PackageManager ;
2022-03-07 12:18:08 +00:00
import android.content.pm.PermissionGroupInfo ;
import android.content.pm.PermissionInfo ;
2023-04-02 08:28:54 +00:00
import android.content.pm.ResolveInfo ;
2023-03-03 07:55:29 +00:00
import android.content.pm.verify.domain.DomainVerificationManager ;
import android.content.pm.verify.domain.DomainVerificationUserState ;
2019-05-12 17:14:34 +00:00
import android.content.res.Configuration ;
2021-01-16 12:13:44 +00:00
import android.content.res.Resources ;
2022-09-29 05:19:39 +00:00
import android.database.Cursor ;
import android.database.sqlite.SQLiteDatabase ;
2020-06-16 05:29:55 +00:00
import android.database.sqlite.SQLiteFullException ;
2019-05-12 17:14:34 +00:00
import android.graphics.Point ;
2022-02-22 18:19:26 +00:00
import android.graphics.Typeface ;
2019-05-12 17:14:34 +00:00
import android.net.ConnectivityManager ;
2020-10-27 14:35:28 +00:00
import android.net.LinkProperties ;
2019-05-12 17:14:34 +00:00
import android.net.Network ;
import android.net.NetworkCapabilities ;
2019-10-22 06:55:27 +00:00
import android.net.NetworkInfo ;
2022-04-06 06:26:27 +00:00
import android.net.Uri ;
2019-05-12 17:14:34 +00:00
import android.os.Build ;
2019-01-25 14:40:46 +00:00
import android.os.Bundle ;
2019-10-12 11:09:14 +00:00
import android.os.DeadObjectException ;
2020-12-13 11:06:30 +00:00
import android.os.DeadSystemException ;
2019-07-22 07:18:03 +00:00
import android.os.Debug ;
2022-09-05 20:51:26 +00:00
import android.os.Environment ;
2021-09-07 15:08:00 +00:00
import android.os.IBinder ;
2022-06-13 07:43:23 +00:00
import android.os.LocaleList ;
2021-07-27 16:32:10 +00:00
import android.os.OperationCanceledException ;
2022-01-17 17:43:13 +00:00
import android.os.PowerManager ;
2019-08-12 11:17:55 +00:00
import android.os.RemoteException ;
2022-06-14 13:55:11 +00:00
import android.os.SystemClock ;
2020-04-20 06:07:41 +00:00
import android.os.TransactionTooLargeException ;
2022-08-10 18:53:01 +00:00
import android.os.ext.SdkExtensions ;
2023-04-25 06:17:29 +00:00
import android.provider.MediaStore ;
2021-08-23 16:03:34 +00:00
import android.provider.Settings ;
2022-02-22 18:19:26 +00:00
import android.text.SpannableStringBuilder ;
2022-08-25 05:56:15 +00:00
import android.text.Spanned ;
2019-01-25 14:40:46 +00:00
import android.text.TextUtils ;
2022-02-22 18:19:26 +00:00
import android.text.style.RelativeSizeSpan ;
import android.text.style.StrikethroughSpan ;
import android.text.style.StyleSpan ;
2022-01-03 18:23:36 +00:00
import android.util.Printer ;
2019-05-12 17:14:34 +00:00
import android.view.Display ;
2020-09-10 16:37:39 +00:00
import android.view.InflateException ;
2021-10-17 05:26:38 +00:00
import android.view.LayoutInflater ;
import android.view.View ;
2023-08-02 14:54:22 +00:00
import android.view.ViewConfiguration ;
2019-05-12 17:14:34 +00:00
import android.view.WindowManager ;
2023-12-06 10:06:33 +00:00
import android.widget.Button ;
2021-10-17 05:26:38 +00:00
import android.widget.TextView ;
2019-05-12 17:14:34 +00:00
2019-08-12 11:17:55 +00:00
import androidx.annotation.NonNull ;
2019-12-06 07:50:46 +00:00
import androidx.annotation.Nullable ;
2020-10-09 12:29:30 +00:00
import androidx.annotation.RequiresApi ;
2019-12-06 07:50:46 +00:00
import androidx.appcompat.app.AlertDialog ;
2023-06-15 20:37:26 +00:00
import androidx.browser.customtabs.CustomTabsClient ;
import androidx.browser.customtabs.CustomTabsServiceConnection ;
2023-09-21 07:12:39 +00:00
import androidx.emoji2.text.EmojiCompat ;
2023-02-10 07:34:31 +00:00
import androidx.fragment.app.Fragment ;
2019-12-06 07:50:46 +00:00
import androidx.fragment.app.FragmentManager ;
2019-05-12 17:14:34 +00:00
import androidx.preference.PreferenceManager ;
2022-06-30 06:02:41 +00:00
import androidx.webkit.WebViewCompat ;
2022-06-10 11:49:19 +00:00
import androidx.webkit.WebViewFeature ;
2023-01-24 07:00:30 +00:00
import androidx.work.WorkInfo ;
import androidx.work.WorkManager ;
import androidx.work.WorkQuery ;
2019-01-25 14:40:46 +00:00
2019-08-12 11:07:14 +00:00
import com.bugsnag.android.BreadcrumbType ;
2019-05-10 06:53:45 +00:00
import com.bugsnag.android.Bugsnag ;
2019-08-12 11:17:55 +00:00
import com.bugsnag.android.Client ;
2020-05-22 17:50:46 +00:00
import com.bugsnag.android.ErrorTypes ;
import com.bugsnag.android.Event ;
import com.bugsnag.android.OnErrorCallback ;
import com.bugsnag.android.OnSessionCallback ;
import com.bugsnag.android.Session ;
2019-05-10 06:53:45 +00:00
import com.bugsnag.android.Severity ;
2019-12-06 07:50:46 +00:00
import com.sun.mail.iap.BadCommandException ;
import com.sun.mail.iap.ConnectionException ;
2019-08-12 11:17:55 +00:00
import com.sun.mail.iap.ProtocolException ;
2019-12-06 07:50:46 +00:00
import com.sun.mail.util.FolderClosedIOException ;
2022-02-16 20:16:26 +00:00
import com.sun.mail.util.MailConnectException ;
2019-05-10 06:53:45 +00:00
2023-03-05 07:42:25 +00:00
import net.openid.appauth.AuthState ;
import net.openid.appauth.TokenResponse ;
2023-11-09 20:17:52 +00:00
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider ;
2019-05-12 17:14:34 +00:00
import org.json.JSONException ;
import org.json.JSONObject ;
import java.io.BufferedOutputStream ;
import java.io.BufferedReader ;
import java.io.File ;
2019-08-12 11:17:55 +00:00
import java.io.FileNotFoundException ;
2019-05-12 17:14:34 +00:00
import java.io.FileOutputStream ;
2019-08-12 11:17:55 +00:00
import java.io.FileWriter ;
2019-05-12 17:14:34 +00:00
import java.io.IOException ;
import java.io.InputStreamReader ;
import java.io.OutputStream ;
import java.io.UnsupportedEncodingException ;
2019-04-24 16:39:32 +00:00
import java.lang.reflect.Array ;
2021-06-20 18:40:08 +00:00
import java.net.InetAddress ;
import java.net.InterfaceAddress ;
import java.net.NetworkInterface ;
2019-12-06 08:00:31 +00:00
import java.net.SocketException ;
2022-02-16 20:16:26 +00:00
import java.net.SocketTimeoutException ;
2022-02-17 10:01:34 +00:00
import java.net.UnknownHostException ;
2020-07-10 08:07:53 +00:00
import java.nio.charset.StandardCharsets ;
2022-05-04 08:47:23 +00:00
import java.nio.file.FileStore ;
import java.nio.file.FileSystems ;
2022-02-22 18:19:26 +00:00
import java.security.KeyStore ;
2021-09-07 18:05:25 +00:00
import java.security.Provider ;
import java.security.Security ;
2020-02-07 08:58:33 +00:00
import java.security.cert.CertPathValidatorException ;
2023-11-11 10:39:53 +00:00
import java.security.cert.X509Certificate ;
2019-05-12 17:14:34 +00:00
import java.text.DateFormat ;
2021-06-17 19:25:51 +00:00
import java.text.DateFormatSymbols ;
2020-08-30 11:35:21 +00:00
import java.text.SimpleDateFormat ;
2019-08-12 11:17:55 +00:00
import java.util.ArrayList ;
2019-09-24 15:05:33 +00:00
import java.util.Arrays ;
2020-04-03 06:59:22 +00:00
import java.util.Collections ;
2022-12-27 14:22:39 +00:00
import java.util.Comparator ;
2019-05-12 17:14:34 +00:00
import java.util.Date ;
2021-06-20 18:40:08 +00:00
import java.util.Enumeration ;
2020-05-22 17:50:46 +00:00
import java.util.HashMap ;
import java.util.HashSet ;
2023-06-15 20:37:26 +00:00
import java.util.Iterator ;
2019-05-12 17:14:34 +00:00
import java.util.List ;
2021-01-16 12:13:44 +00:00
import java.util.Locale ;
2019-05-12 17:14:34 +00:00
import java.util.Map ;
2023-04-02 08:28:54 +00:00
import java.util.Objects ;
2022-05-12 09:09:57 +00:00
import java.util.Properties ;
2019-01-25 14:40:46 +00:00
import java.util.Set ;
2022-08-11 05:38:49 +00:00
import java.util.TimeZone ;
2019-08-12 11:17:55 +00:00
import java.util.UUID ;
import java.util.concurrent.TimeoutException ;
2019-01-25 14:40:46 +00:00
2019-05-12 17:14:34 +00:00
import javax.mail.Address ;
2019-12-06 08:00:31 +00:00
import javax.mail.AuthenticationFailedException ;
2019-12-06 07:50:46 +00:00
import javax.mail.FolderClosedException ;
import javax.mail.MessageRemovedException ;
2019-08-12 11:17:55 +00:00
import javax.mail.MessagingException ;
2019-06-29 06:52:15 +00:00
import javax.mail.Part ;
2019-12-09 07:37:08 +00:00
import javax.mail.StoreClosedException ;
2019-05-12 17:14:34 +00:00
import javax.mail.internet.InternetAddress ;
2020-07-10 09:08:12 +00:00
import javax.mail.internet.MimeUtility ;
2022-02-22 18:19:26 +00:00
import javax.net.ssl.SSLContext ;
2020-02-07 08:58:33 +00:00
import javax.net.ssl.SSLHandshakeException ;
2020-02-02 14:24:24 +00:00
import javax.net.ssl.SSLPeerUnverifiedException ;
2022-02-22 18:19:26 +00:00
import javax.net.ssl.SSLSocket ;
2022-02-23 09:30:51 +00:00
import javax.net.ssl.TrustManager ;
2022-02-22 18:19:26 +00:00
import javax.net.ssl.TrustManagerFactory ;
2023-11-11 10:39:53 +00:00
import javax.net.ssl.X509TrustManager ;
2019-05-12 17:14:34 +00:00
2018-12-24 12:27:45 +00:00
public class Log {
2021-10-22 13:04:16 +00:00
private static Context ctx ;
2021-02-27 16:45:08 +00:00
private static int level = android . util . Log . INFO ;
2022-06-14 05:51:57 +00:00
private static final long MAX_LOG_SIZE = 8 * 1024 * 1024L ;
2022-02-23 11:39:01 +00:00
private static final int MAX_CRASH_REPORTS = ( BuildConfig . TEST_RELEASE ? 50 : 5 ) ;
2022-12-27 14:22:39 +00:00
private static final long MIN_FILE_SIZE = 1024 * 1024L ;
2023-01-04 07:17:52 +00:00
private static final long MIN_ZIP_SIZE = 2 * 1024 * 1024L ;
2019-08-12 11:33:39 +00:00
private static final String TAG = " fairemail " ;
2018-12-24 12:27:45 +00:00
2022-09-09 06:21:15 +00:00
// https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
// https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html
private static final List < String > NETWORK_PROPS = Collections . unmodifiableList ( Arrays . asList (
" java.net.preferIPv4Stack " ,
" java.net.preferIPv6Addresses " ,
" http.proxyHost " ,
" http.proxyPort " ,
" http.nonProxyHosts " ,
" https.proxyHost " ,
" https.proxyPort " ,
//"ftp.proxyHost",
//"ftp.proxyPort",
//"ftp.nonProxyHosts",
" socksProxyHost " ,
" socksProxyPort " ,
" socksProxyVersion " ,
" java.net.socks.username " ,
//"java.net.socks.password",
" http.agent " ,
" http.keepalive " ,
" http.maxConnections " ,
" http.maxRedirects " ,
" http.auth.digest.validateServer " ,
" http.auth.digest.validateProxy " ,
" http.auth.digest.cnonceRepeat " ,
" http.auth.ntlm.domain " ,
" jdk.https.negotiate.cbt " ,
" networkaddress.cache.ttl " ,
" networkaddress.cache.negative.ttl "
) ) ;
2021-12-01 18:33:29 +00:00
static final String TOKEN_REFRESH_REQUIRED =
" Token refresh required. Is there a VPN based app running? " ;
2021-02-27 16:45:08 +00:00
public static void setLevel ( Context context ) {
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
boolean debug = prefs . getBoolean ( " debug " , false ) ;
if ( debug )
level = android . util . Log . DEBUG ;
2022-11-25 08:21:58 +00:00
else {
int def = ( BuildConfig . DEBUG ? android . util . Log . INFO : android . util . Log . WARN ) ;
level = prefs . getInt ( " log_level " , def ) ;
}
2021-02-27 16:45:08 +00:00
android . util . Log . d ( TAG , " Log level= " + level ) ;
}
2022-11-25 08:21:58 +00:00
public static boolean isDebugLogLevel ( ) {
return ( level < = android . util . Log . INFO ) ;
2020-04-05 12:10:42 +00:00
}
2019-08-11 13:49:14 +00:00
public static int d ( String msg ) {
2021-02-27 16:45:08 +00:00
if ( level < = android . util . Log . DEBUG )
2019-08-11 13:49:14 +00:00
return android . util . Log . d ( TAG , msg ) ;
else
return 0 ;
}
2021-02-27 16:45:08 +00:00
public static int d ( String tag , String msg ) {
if ( level < = android . util . Log . DEBUG )
return android . util . Log . d ( tag , msg ) ;
else
return 0 ;
}
2018-12-24 12:27:45 +00:00
public static int i ( String msg ) {
2023-08-22 14:52:56 +00:00
if ( level < = android . util . Log . INFO | | BuildConfig . DEBUG | | BuildConfig . TEST_RELEASE )
2018-12-28 09:56:40 +00:00
return android . util . Log . i ( TAG , msg ) ;
else
return 0 ;
2018-12-24 12:27:45 +00:00
}
2021-02-27 16:45:08 +00:00
public static int i ( String tag , String msg ) {
2023-08-22 14:52:56 +00:00
if ( level < = android . util . Log . INFO | | BuildConfig . DEBUG | | BuildConfig . TEST_RELEASE )
2021-02-27 16:45:08 +00:00
return android . util . Log . i ( tag , msg ) ;
else
return 0 ;
}
2018-12-24 12:27:45 +00:00
public static int w ( String msg ) {
return android . util . Log . w ( TAG , msg ) ;
}
public static int e ( String msg ) {
2019-12-14 16:01:27 +00:00
if ( BuildConfig . BETA_RELEASE )
try {
2020-05-22 17:50:46 +00:00
Throwable ex = new Throwable ( msg ) ;
List < StackTraceElement > ss = new ArrayList < > ( Arrays . asList ( ex . getStackTrace ( ) ) ) ;
2019-12-14 16:01:27 +00:00
ss . remove ( 0 ) ;
2020-05-22 17:50:46 +00:00
ex . setStackTrace ( ss . toArray ( new StackTraceElement [ 0 ] ) ) ;
Bugsnag . notify ( ex , new OnErrorCallback ( ) {
2019-12-14 16:01:27 +00:00
@Override
2020-05-22 17:50:46 +00:00
public boolean onError ( @NonNull Event event ) {
event . setSeverity ( Severity . ERROR ) ;
return true ;
2019-12-14 16:01:27 +00:00
}
} ) ;
} catch ( Throwable ex ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex ) ;
2019-12-14 16:01:27 +00:00
}
2018-12-24 12:27:45 +00:00
return android . util . Log . e ( TAG , msg ) ;
}
2019-05-14 08:07:05 +00:00
public static int i ( Throwable ex ) {
2019-06-09 13:51:24 +00:00
return android . util . Log . i ( TAG , ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
2019-05-14 08:07:05 +00:00
}
2018-12-24 12:27:45 +00:00
public static int w ( Throwable ex ) {
2019-05-15 19:20:18 +00:00
if ( BuildConfig . BETA_RELEASE )
2019-12-14 16:01:27 +00:00
try {
2021-07-30 19:41:53 +00:00
final StackTraceElement [ ] ste = new Throwable ( ) . getStackTrace ( ) ;
2020-05-22 17:50:46 +00:00
Bugsnag . notify ( ex , new OnErrorCallback ( ) {
@Override
public boolean onError ( @NonNull Event event ) {
event . setSeverity ( Severity . INFO ) ;
2021-07-30 19:41:53 +00:00
if ( ste . length > 1 )
event . addMetadata ( " extra " , " caller " , ste [ 1 ] . toString ( ) ) ;
2020-05-22 17:50:46 +00:00
return true ;
}
} ) ;
2019-12-14 16:01:27 +00:00
} catch ( Throwable ex1 ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex1 ) ;
2019-12-14 16:01:27 +00:00
}
2018-12-24 12:27:45 +00:00
return android . util . Log . w ( TAG , ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
}
public static int e ( Throwable ex ) {
2019-05-15 19:20:18 +00:00
if ( BuildConfig . BETA_RELEASE )
2019-12-14 16:01:27 +00:00
try {
2021-07-30 19:41:53 +00:00
final StackTraceElement [ ] ste = new Throwable ( ) . getStackTrace ( ) ;
2020-05-22 17:50:46 +00:00
Bugsnag . notify ( ex , new OnErrorCallback ( ) {
@Override
public boolean onError ( @NonNull Event event ) {
event . setSeverity ( Severity . WARNING ) ;
2021-07-30 19:41:53 +00:00
if ( ste . length > 1 )
event . addMetadata ( " extra " , " caller " , ste [ 1 ] . toString ( ) ) ;
2020-05-22 17:50:46 +00:00
return true ;
}
} ) ;
2019-12-14 16:01:27 +00:00
} catch ( Throwable ex1 ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex1 ) ;
2019-12-14 16:01:27 +00:00
}
2018-12-24 12:27:45 +00:00
return android . util . Log . e ( TAG , ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
}
2020-04-15 11:42:53 +00:00
public static int i ( String prefix , Throwable ex ) {
return android . util . Log . i ( TAG , prefix + " " + ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
}
2018-12-24 12:27:45 +00:00
public static int w ( String prefix , Throwable ex ) {
2019-05-15 19:20:18 +00:00
if ( BuildConfig . BETA_RELEASE )
2019-12-14 16:01:27 +00:00
try {
2020-05-22 17:50:46 +00:00
Bugsnag . notify ( ex , new OnErrorCallback ( ) {
@Override
public boolean onError ( @NonNull Event event ) {
event . setSeverity ( Severity . INFO ) ;
return true ;
}
} ) ;
2019-12-14 16:01:27 +00:00
} catch ( Throwable ex1 ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex1 ) ;
2019-12-14 16:01:27 +00:00
}
2018-12-24 12:27:45 +00:00
return android . util . Log . w ( TAG , prefix + " " + ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
}
public static int e ( String prefix , Throwable ex ) {
2019-05-15 19:20:18 +00:00
if ( BuildConfig . BETA_RELEASE )
2019-12-14 16:01:27 +00:00
try {
2020-05-22 17:50:46 +00:00
Bugsnag . notify ( ex , new OnErrorCallback ( ) {
@Override
public boolean onError ( @NonNull Event event ) {
event . setSeverity ( Severity . WARNING ) ;
return true ;
}
} ) ;
2019-12-14 16:01:27 +00:00
} catch ( Throwable ex1 ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex1 ) ;
2019-12-14 16:01:27 +00:00
}
2018-12-24 12:27:45 +00:00
return android . util . Log . e ( TAG , prefix + " " + ex + " \ n " + android . util . Log . getStackTraceString ( ex ) ) ;
}
2019-01-25 14:40:46 +00:00
2021-10-22 13:04:16 +00:00
public static void persist ( String message ) {
if ( ctx = = null )
Log . e ( message ) ;
else
EntityLog . log ( ctx , message ) ;
}
2022-11-09 13:02:24 +00:00
public static void persist ( EntityLog . Type type , String message ) {
if ( ctx = = null )
Log . e ( message ) ;
else
EntityLog . log ( ctx , type , message ) ;
}
2019-08-12 11:17:55 +00:00
static void setCrashReporting ( boolean enabled ) {
2019-12-14 16:01:27 +00:00
try {
if ( enabled )
Bugsnag . startSession ( ) ;
} catch ( Throwable ex ) {
2023-12-06 16:06:46 +00:00
Log . i ( ex ) ;
2019-12-14 16:01:27 +00:00
}
2019-08-12 11:17:55 +00:00
}
2023-11-29 06:41:28 +00:00
public static void breadcrumb ( String name , Bundle args ) {
Map < String , String > crumb = new HashMap < > ( ) ;
for ( String key : args . keySet ( ) ) {
Object value = args . get ( key ) ;
if ( value instanceof Boolean )
crumb . put ( key , Boolean . toString ( ( Boolean ) value ) ) ;
else if ( value instanceof Integer )
crumb . put ( key , Integer . toString ( ( Integer ) value ) ) ;
else if ( value instanceof Long )
crumb . put ( key , Long . toString ( ( Long ) value ) ) ;
else if ( value instanceof Float )
crumb . put ( key , Float . toString ( ( Float ) value ) ) ;
else if ( value instanceof Double )
crumb . put ( key , Double . toString ( ( Double ) value ) ) ;
else if ( value instanceof String | | value instanceof Spanned ) {
String v = value . toString ( ) ;
if ( v . length ( ) > 50 )
v = v . substring ( 0 , 50 ) + " ... " ;
crumb . put ( key , v ) ;
} else if ( value = = null )
crumb . put ( key , " <null> " ) ;
else
crumb . put ( key , " < " + value . getClass ( ) . getName ( ) + " > " ) ;
}
breadcrumb ( name , crumb ) ;
}
2021-07-27 14:17:15 +00:00
public static void breadcrumb ( String name , String key , String value ) {
2021-05-14 17:20:01 +00:00
Map < String , String > crumb = new HashMap < > ( ) ;
crumb . put ( key , value ) ;
breadcrumb ( name , crumb ) ;
}
2021-07-27 14:17:15 +00:00
public static void breadcrumb ( String name , Map < String , String > crumb ) {
2019-12-14 16:01:27 +00:00
try {
2022-05-02 08:44:42 +00:00
crumb . put ( " free " , Integer . toString ( Log . getFreeMemMb ( ) ) ) ;
2021-07-27 14:17:15 +00:00
StringBuilder sb = new StringBuilder ( ) ;
sb . append ( " Breadcrumb " ) . append ( name ) ;
2020-05-22 17:50:46 +00:00
Map < String , Object > ocrumb = new HashMap < > ( ) ;
2021-07-27 14:17:15 +00:00
for ( String key : crumb . keySet ( ) ) {
String val = crumb . get ( key ) ;
sb . append ( ' ' ) . append ( key ) . append ( '=' ) . append ( val ) ;
ocrumb . put ( key , val ) ;
}
2021-09-16 06:13:34 +00:00
Log . i ( sb . toString ( ) ) ;
2020-05-22 17:50:46 +00:00
Bugsnag . leaveBreadcrumb ( name , ocrumb , BreadcrumbType . LOG ) ;
2019-12-14 16:01:27 +00:00
} catch ( Throwable ex ) {
2023-12-06 16:06:46 +00:00
Log . e ( ex ) ;
2019-12-14 16:01:27 +00:00
}
2019-08-12 11:17:55 +00:00
}
2020-04-05 12:10:42 +00:00
static void setup ( Context context ) {
2021-10-22 13:04:16 +00:00
ctx = context ;
2021-02-27 16:45:08 +00:00
setLevel ( context ) ;
2020-04-05 12:10:42 +00:00
setupBugsnag ( context ) ;
}
2020-05-28 18:49:59 +00:00
private static void setupBugsnag ( final Context context ) {
2021-01-27 16:58:16 +00:00
try {
2021-02-27 15:00:31 +00:00
Log . i ( " Configuring Bugsnag " ) ;
2021-01-27 16:58:16 +00:00
// https://docs.bugsnag.com/platforms/android/sdk/
com . bugsnag . android . Configuration config =
new com . bugsnag . android . Configuration ( " 9d2d57476a0614974449a3ec33f2604a " ) ;
2022-06-23 18:23:15 +00:00
config . setTelemetry ( Collections . emptySet ( ) ) ;
2021-01-27 16:58:16 +00:00
if ( BuildConfig . DEBUG )
2023-10-26 06:42:04 +00:00
config . setReleaseStage ( " Debug " ) ;
else
config . setReleaseStage ( getReleaseType ( context ) ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
config . setAutoTrackSessions ( false ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ErrorTypes etypes = new ErrorTypes ( ) ;
etypes . setAnrs ( BuildConfig . DEBUG ) ;
etypes . setNdkCrashes ( false ) ;
config . setEnabledErrorTypes ( etypes ) ;
2022-11-13 07:54:15 +00:00
config . setMaxBreadcrumbs ( BuildConfig . PLAY_STORE_RELEASE ? 250 : 500 ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
Set < String > ignore = new HashSet < > ( ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " com.sun.mail.util.MailConnectException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " android.accounts.AuthenticatorException " ) ;
ignore . add ( " android.accounts.OperationCanceledException " ) ;
ignore . add ( " android.app.RemoteServiceException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " java.lang.NoClassDefFoundError " ) ;
ignore . add ( " java.lang.UnsatisfiedLinkError " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " java.nio.charset.MalformedInputException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " java.net.ConnectException " ) ;
ignore . add ( " java.net.SocketException " ) ;
ignore . add ( " java.net.SocketTimeoutException " ) ;
ignore . add ( " java.net.UnknownHostException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " javax.mail.AuthenticationFailedException " ) ;
ignore . add ( " javax.mail.internet.AddressException " ) ;
ignore . add ( " javax.mail.internet.ParseException " ) ;
ignore . add ( " javax.mail.MessageRemovedException " ) ;
ignore . add ( " javax.mail.FolderNotFoundException " ) ;
ignore . add ( " javax.mail.ReadOnlyFolderException " ) ;
ignore . add ( " javax.mail.FolderClosedException " ) ;
ignore . add ( " com.sun.mail.util.FolderClosedIOException " ) ;
ignore . add ( " javax.mail.StoreClosedException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
ignore . add ( " org.xmlpull.v1.XmlPullParserException " ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
config . setDiscardClasses ( ignore ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
final SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
2022-04-13 20:27:33 +00:00
ActivityManager am = Helper . getSystemService ( context , ActivityManager . class ) ;
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
String no_internet = context . getString ( R . string . title_no_internet ) ;
2020-02-01 14:52:53 +00:00
2023-11-03 15:39:44 +00:00
String installer = Helper . getInstallerName ( context ) ;
2021-10-04 06:47:06 +00:00
config . addMetadata ( " extra " , " revision " , BuildConfig . REVISION ) ;
2021-01-27 16:58:16 +00:00
config . addMetadata ( " extra " , " installer " , installer = = null ? " - " : installer ) ;
config . addMetadata ( " extra " , " installed " , new Date ( Helper . getInstallTime ( context ) ) . toString ( ) ) ;
config . addMetadata ( " extra " , " fingerprint " , Helper . hasValidFingerprint ( context ) ) ;
config . addMetadata ( " extra " , " memory_class " , am . getMemoryClass ( ) ) ;
config . addMetadata ( " extra " , " memory_class_large " , am . getLargeMemoryClass ( ) ) ;
2021-11-03 07:01:23 +00:00
config . addMetadata ( " extra " , " build_host " , Build . HOST ) ;
config . addMetadata ( " extra " , " build_time " , new Date ( Build . TIME ) ) ;
2020-05-22 17:50:46 +00:00
2021-01-27 16:58:16 +00:00
config . addOnSession ( new OnSessionCallback ( ) {
@Override
public boolean onSession ( @NonNull Session session ) {
// opt-in
2022-01-09 13:48:37 +00:00
return prefs . getBoolean ( " crash_reports " , false ) | | BuildConfig . TEST_RELEASE ;
2020-05-22 17:50:46 +00:00
}
2021-01-27 16:58:16 +00:00
} ) ;
config . addOnError ( new OnErrorCallback ( ) {
@Override
public boolean onError ( @NonNull Event event ) {
// opt-in
boolean crash_reports = prefs . getBoolean ( " crash_reports " , false ) ;
2022-01-09 13:48:37 +00:00
if ( ! crash_reports & & ! BuildConfig . TEST_RELEASE )
2021-01-27 16:58:16 +00:00
return false ;
Throwable ex = event . getOriginalError ( ) ;
boolean should = shouldNotify ( ex ) ;
if ( should ) {
2021-04-25 14:27:28 +00:00
event . addMetadata ( " extra " , " pid " , Integer . toString ( android . os . Process . myPid ( ) ) ) ;
2021-01-27 16:58:16 +00:00
event . addMetadata ( " extra " , " thread " , Thread . currentThread ( ) . getName ( ) + " : " + Thread . currentThread ( ) . getId ( ) ) ;
event . addMetadata ( " extra " , " memory_free " , getFreeMemMb ( ) ) ;
event . addMetadata ( " extra " , " memory_available " , getAvailableMb ( ) ) ;
2021-08-31 05:40:08 +00:00
event . addMetadata ( " extra " , " native_allocated " , Debug . getNativeHeapAllocatedSize ( ) / 1024L / 1024L ) ;
event . addMetadata ( " extra " , " native_size " , Debug . getNativeHeapSize ( ) / 1024L / 1024L ) ;
2023-01-11 09:20:32 +00:00
event . addMetadata ( " extra " , " classifier_size " , MessageClassifier . getSize ( context ) ) ;
2021-01-27 16:58:16 +00:00
Boolean ignoringOptimizations = Helper . isIgnoringOptimizations ( context ) ;
event . addMetadata ( " extra " , " optimizing " , ( ignoringOptimizations ! = null & & ! ignoringOptimizations ) ) ;
String theme = prefs . getString ( " theme " , " blue_orange_system " ) ;
event . addMetadata ( " extra " , " theme " , theme ) ;
event . addMetadata ( " extra " , " package " , BuildConfig . APPLICATION_ID ) ;
2023-07-24 08:47:57 +00:00
event . addMetadata ( " extra " , " locale " , Locale . getDefault ( ) . toString ( ) ) ;
2021-01-27 16:58:16 +00:00
}
2020-05-22 17:50:46 +00:00
2021-01-27 16:58:16 +00:00
return should ;
}
2019-08-12 11:17:55 +00:00
2021-01-27 16:58:16 +00:00
private boolean shouldNotify ( Throwable ex ) {
if ( ex instanceof MessagingException & &
( ex . getCause ( ) instanceof IOException | |
ex . getCause ( ) instanceof ProtocolException ) )
// IOException includes SocketException, SocketTimeoutException
// ProtocolException includes ConnectionException
return false ;
if ( ex instanceof MessagingException & &
( " connection failure " . equals ( ex . getMessage ( ) ) | |
" failed to create new store connection " . equals ( ex . getMessage ( ) ) | |
" Failed to fetch headers " . equals ( ex . getMessage ( ) ) | |
" Failed to load IMAP envelope " . equals ( ex . getMessage ( ) ) | |
" Unable to load BODYSTRUCTURE " . equals ( ex . getMessage ( ) ) ) )
return false ;
if ( ex instanceof IllegalStateException & &
( no_internet . equals ( ex . getMessage ( ) ) | |
2021-12-01 18:33:29 +00:00
TOKEN_REFRESH_REQUIRED . equals ( ex . getMessage ( ) ) | |
2021-01-27 16:58:16 +00:00
" Not connected " . equals ( ex . getMessage ( ) ) | |
" This operation is not allowed on a closed folder " . equals ( ex . getMessage ( ) ) ) )
return false ;
if ( ex instanceof FileNotFoundException & &
ex . getMessage ( ) ! = null & &
( ex . getMessage ( ) . startsWith ( " Download image failed " ) | |
ex . getMessage ( ) . startsWith ( " http:// " ) | |
ex . getMessage ( ) . startsWith ( " https:// " ) | |
ex . getMessage ( ) . startsWith ( " content:// " ) ) )
return false ;
if ( ex instanceof IOException & &
ex . getCause ( ) instanceof MessageRemovedException )
return false ;
if ( ex instanceof IOException & &
ex . getMessage ( ) ! = null & &
( ex . getMessage ( ) . startsWith ( " HTTP status= " ) | |
" NetworkError " . equals ( ex . getMessage ( ) ) | | // account manager
" Resetting to invalid mark " . equals ( ex . getMessage ( ) ) | |
" Mark has been invalidated. " . equals ( ex . getMessage ( ) ) ) )
return false ;
if ( ex instanceof SSLPeerUnverifiedException | |
ex instanceof EmailService . UntrustedException )
return false ;
if ( ex instanceof SSLHandshakeException & &
ex . getCause ( ) instanceof CertPathValidatorException )
return false ; // checkUpdate!
if ( ex instanceof RuntimeException & &
" Illegal meta data value: the child service doesn't exist " . equals ( ex . getMessage ( ) ) )
return false ;
2021-01-31 11:25:10 +00:00
if ( isDead ( ex ) )
return false ;
2021-01-27 16:58:16 +00:00
// Rate limit
int count = prefs . getInt ( " crash_report_count " , 0 ) + 1 ;
prefs . edit ( ) . putInt ( " crash_report_count " , count ) . apply ( ) ;
return ( count < = MAX_CRASH_REPORTS ) ;
}
} ) ;
2019-10-28 17:46:53 +00:00
2021-01-27 16:58:16 +00:00
Bugsnag . start ( context , config ) ;
2019-10-28 17:46:53 +00:00
2021-01-27 16:58:16 +00:00
Client client = Bugsnag . getClient ( ) ;
2019-10-28 17:46:53 +00:00
2021-01-27 16:58:16 +00:00
String uuid = prefs . getString ( " uuid " , null ) ;
if ( uuid = = null ) {
uuid = UUID . randomUUID ( ) . toString ( ) ;
prefs . edit ( ) . putString ( " uuid " , uuid ) . apply ( ) ;
}
Log . i ( " uuid= " + uuid ) ;
client . setUser ( uuid , null , null ) ;
2019-10-28 17:46:53 +00:00
2022-01-09 13:48:37 +00:00
if ( prefs . getBoolean ( " crash_reports " , false ) | | BuildConfig . TEST_RELEASE )
2021-01-27 16:58:16 +00:00
Bugsnag . startSession ( ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
/ *
java . lang . AssertionError : No NameTypeIndex match for SHORT_DAYLIGHT
at android . icu . impl . TimeZoneNamesImpl$ZNames . getNameTypeIndex ( TimeZoneNamesImpl . java : 724 )
at android . icu . impl . TimeZoneNamesImpl$ZNames . getName ( TimeZoneNamesImpl . java : 790 )
at android . icu . impl . TimeZoneNamesImpl . getTimeZoneDisplayName ( TimeZoneNamesImpl . java : 183 )
at android . icu . text . TimeZoneNames . getDisplayName ( TimeZoneNames . java : 261 )
at java . util . TimeZone . getDisplayName ( TimeZone . java : 405 )
at java . util . Date . toString ( Date . java : 1066 )
* /
}
2019-08-12 11:07:14 +00:00
}
2023-11-03 15:39:44 +00:00
static @NonNull String getReleaseType ( Context context ) {
2023-10-26 06:42:04 +00:00
if ( Helper . hasValidFingerprint ( context ) ) {
2023-11-03 15:39:44 +00:00
if ( BuildConfig . PLAY_STORE_RELEASE ) {
String installer = Helper . getInstallerName ( context ) ;
String type = " Play Store " ;
if ( installer ! = null & & ! Helper . PLAY_PACKAGE_NAME . equals ( installer ) )
type + = " ( " + installer + " ) " ;
return type ;
} else if ( BuildConfig . FDROID_RELEASE )
2023-10-26 06:42:04 +00:00
return " Reproducible " ;
else if ( BuildConfig . AMAZON_RELEASE )
return " Amazon " ;
else
return " GitHub " ;
} else if ( Helper . isSignedByFDroid ( context ) )
return " F-Droid " ;
else {
if ( BuildConfig . APPLICATION_ID . startsWith ( " eu.faircode.email " ) )
return " Other " ;
else
return " Clone " ;
}
}
2019-05-15 19:20:18 +00:00
static void logExtras ( Intent intent ) {
2019-01-25 14:40:46 +00:00
if ( intent ! = null )
logBundle ( intent . getExtras ( ) ) ;
}
2019-05-15 19:20:18 +00:00
static void logBundle ( Bundle data ) {
2019-10-01 07:19:44 +00:00
for ( String extra : getExtras ( data ) )
i ( extra ) ;
}
static List < String > getExtras ( Bundle data ) {
List < String > result = new ArrayList < > ( ) ;
if ( data = = null )
return result ;
2019-10-29 06:57:39 +00:00
try {
Set < String > keys = data . keySet ( ) ;
for ( String key : keys ) {
Object v = data . get ( key ) ;
Object value = v ;
2021-12-06 07:50:59 +00:00
int length = - 1 ;
2019-10-29 06:57:39 +00:00
if ( v ! = null & & v . getClass ( ) . isArray ( ) ) {
2021-12-06 07:50:59 +00:00
length = Array . getLength ( v ) ;
String [ ] elements = new String [ Math . min ( length , 10 ) ] ;
for ( int i = 0 ; i < elements . length ; i + + ) {
Object element = Array . get ( v , i ) ;
if ( element instanceof Long )
elements [ i ] = element + " (0x " + Long . toHexString ( ( Long ) element ) + " ) " ;
2022-08-25 05:56:15 +00:00
else if ( element instanceof Spanned )
2023-08-26 10:27:38 +00:00
elements [ i ] = " (span: " + Helper . getPrintableString ( element . toString ( ) ) + " ) " ;
2021-12-06 07:50:59 +00:00
else
2023-02-23 19:52:10 +00:00
elements [ i ] = ( element = = null ? " <null> " : Helper . getPrintableString ( element . toString ( ) ) ) ;
2021-12-06 07:50:59 +00:00
}
value = TextUtils . join ( " , " , elements ) ;
if ( length > 10 )
value + = " , ... " ;
value = " [ " + value + " ] " ;
2019-10-29 06:57:39 +00:00
} else if ( v instanceof Long )
2021-12-06 07:50:59 +00:00
value = v + " (0x " + Long . toHexString ( ( Long ) v ) + " ) " ;
2022-08-25 05:56:15 +00:00
else if ( v instanceof Spanned )
2023-08-26 10:27:38 +00:00
value = " (span: " + Helper . getPrintableString ( v . toString ( ) ) + " ) " ;
2021-12-06 07:50:59 +00:00
else if ( v instanceof Bundle )
value = " { " + TextUtils . join ( " " , getExtras ( ( Bundle ) v ) ) + " } " ;
2019-10-01 07:19:44 +00:00
2021-12-06 07:50:59 +00:00
result . add ( key + " = " + value + ( value = = null ? " " :
" ( " + v . getClass ( ) . getSimpleName ( ) + ( length < 0 ? " " : " : " + length ) + " ) " ) ) ;
2019-10-29 06:57:39 +00:00
}
2021-12-17 13:30:28 +00:00
} catch ( Throwable ex ) {
2019-10-29 06:57:39 +00:00
// android.os.BadParcelableException: ClassNotFoundException when unmarshalling: ...
2021-12-17 13:30:28 +00:00
// java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1172374955, result=0, data=Intent { (has extras) }} to activity {eu.faircode.email/eu.faircode.email.ActivityCompose}: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.lyrebirdstudio.imagecameralib.utils.ImageCameraLibReturnTypes)
// at android.app.ActivityThread.deliverResults(ActivityThread.java:4382)
// at android.app.ActivityThread.handleSendResult(ActivityThread.java:4426)
// at android.app.ActivityThread.-wrap20(Unknown)
// at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1685)
// at android.os.Handler.dispatchMessage(Handler.java:106)
// at android.os.Looper.loop(Looper.java:164)
// at android.app.ActivityThread.main(ActivityThread.java:6626)
// at java.lang.reflect.Method.invoke(Method.java:-2)
// at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
//
// Caused by: java.lang.RuntimeException: Parcelable encountered ClassNotFoundException reading a Serializable object (name = com.lyrebirdstudio.imagecameralib.utils.ImageCameraLibReturnTypes)
// at android.os.Parcel.readSerializable(Parcel.java:3019)
// at android.os.Parcel.readValue(Parcel.java:2805)
// at android.os.Parcel.readArrayMapInternal(Parcel.java:3123)
// at android.os.BaseBundle.initializeFromParcelLocked(BaseBundle.java:273)
// at android.os.BaseBundle.unparcel(BaseBundle.java:226)
// at android.os.BaseBundle.keySet(BaseBundle.java:520)
// at eu.faircode.email.Log.getExtras(Log:565)
// at eu.faircode.email.Log.logBundle(Log:555)
// at eu.faircode.email.Log.logExtras(Log:551)
// at eu.faircode.email.ActivityBase.onActivityResult(ActivityBase:376)
// at android.app.Activity.dispatchActivityResult(Activity.java:7305)
// at android.app.ActivityThread.deliverResults(ActivityThread.java:4378)
// at android.app.ActivityThread.handleSendResult(ActivityThread.java:4426)
// at android.app.ActivityThread.-wrap20(Unknown)
// at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1685)
// at android.os.Handler.dispatchMessage(Handler.java:106)
// at android.os.Looper.loop(Looper.java:164)
// at android.app.ActivityThread.main(ActivityThread.java:6626)
// at java.lang.reflect.Method.invoke(Method.java:-2)
// at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
// at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
//
// Caused by: java.lang.ClassNotFoundException: com.lyrebirdstudio.imagecameralib.utils.ImageCameraLibReturnTypes
//
// Caused by: java.lang.ClassNotFoundException: Didn't find class "com.lyrebirdstudio.imagecameralib.utils.ImageCameraLibReturnTypes" on path: DexPathList[[zip file "/data/app/eu.faircode.email-b4dvFM1MrZ5iBeNXAXRJhQ==/base.apk"],nativeLibraryDirectories=[/data/app/eu.faircode.email-b4dvFM1MrZ5iBeNXAXRJhQ==/lib/arm, /data/app/eu.faircode.email-b4dvFM1MrZ5iBeNXAXRJhQ==/base.apk!/lib/armeabi-v7a, /system/lib, /system/vendor/lib]]
2019-10-29 06:57:39 +00:00
Log . e ( ex ) ;
2019-01-25 14:40:46 +00:00
}
2019-10-01 07:19:44 +00:00
return result ;
2019-01-25 14:40:46 +00:00
}
2019-05-12 17:14:34 +00:00
2019-08-12 11:17:55 +00:00
static void logMemory ( Context context , String message ) {
ActivityManager . MemoryInfo mi = new ActivityManager . MemoryInfo ( ) ;
2022-04-13 20:27:33 +00:00
ActivityManager activityManager = Helper . getSystemService ( context , ActivityManager . class ) ;
2019-08-12 11:17:55 +00:00
activityManager . getMemoryInfo ( mi ) ;
int mb = Math . round ( mi . availMem / 0x100000L ) ;
int perc = Math . round ( mi . availMem / ( float ) mi . totalMem * 100 . 0f ) ;
Log . i ( message + " " + mb + " MB " + " " + perc + " % " ) ;
}
2019-08-12 14:18:41 +00:00
static boolean isOwnFault ( Throwable ex ) {
2021-05-28 18:22:01 +00:00
if ( ! Helper . isSupportedDevice ( ) )
2019-09-02 12:52:49 +00:00
return false ;
2020-11-20 08:35:53 +00:00
if ( ex instanceof OutOfMemoryError | |
ex . getCause ( ) instanceof OutOfMemoryError )
2019-08-12 11:17:55 +00:00
return false ;
if ( ex instanceof RemoteException )
return false ;
2020-03-09 12:07:22 +00:00
if ( ex instanceof UnsatisfiedLinkError | |
ex . getCause ( ) instanceof UnsatisfiedLinkError )
2020-03-25 09:05:51 +00:00
/ *
java . lang . UnsatisfiedLinkError : dlopen failed : couldn ' t map " /mnt/asec/eu.faircode.email-1/base.apk!/lib/arm64-v8a/libsqlite3x.so " segment 0 : Permission denied
at java . lang . Runtime . loadLibrary0 ( Runtime . java : 1016 )
at java . lang . System . loadLibrary ( System . java : 1657 )
at io . requery . android . database . sqlite . SQLiteDatabase . < clinit > ( SourceFile : 91 )
* /
2020-03-08 17:12:21 +00:00
return false ;
2020-04-01 12:38:49 +00:00
if ( ex instanceof InternalError & &
" Thread starting during runtime shutdown " . equals ( ex . getMessage ( ) ) )
/ *
java . lang . InternalError : Thread starting during runtime shutdown
at java . lang . Thread . nativeCreate ( Native Method )
at java . lang . Thread . start ( Thread . java : 1063 )
at java . util . concurrent . ThreadPoolExecutor . addWorker ( ThreadPoolExecutor . java : 921 )
at java . util . concurrent . ThreadPoolExecutor . processWorkerExit ( ThreadPoolExecutor . java : 989 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . java : 1131 )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 588 )
at java . lang . Thread . run ( Thread . java : 818 )
* /
return false ;
2020-01-23 11:46:11 +00:00
if ( " android.app.RemoteServiceException " . equals ( ex . getClass ( ) . getName ( ) ) )
2020-03-25 09:05:51 +00:00
/ *
android . app . RemoteServiceException : Bad notification for startForeground : java . util . ConcurrentModificationException
2020-08-06 11:52:27 +00:00
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 2204 )
2020-03-25 09:05:51 +00:00
* /
2020-01-23 11:46:11 +00:00
return false ;
2022-10-22 12:53:21 +00:00
if ( " android.app.RemoteServiceException$CannotDeliverBroadcastException " . equals ( ex . getClass ( ) . getName ( ) ) )
/ *
android . app . RemoteServiceException$CannotDeliverBroadcastException : can ' t deliver broadcast
at android . app . ActivityThread . throwRemoteServiceException ( ActivityThread . java : 2180 )
at android . app . ActivityThread . access$3000 ( ActivityThread . java : 324 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 2435 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
* /
return false ;
2022-12-09 08:09:11 +00:00
if ( " android.app.RemoteServiceException$CannotPostForegroundServiceNotificationException " . equals ( ex . getClass ( ) . getName ( ) ) )
/ *
android . app . RemoteServiceException$CannotPostForegroundServiceNotificationException : Bad notification for startForeground
at android . app . ActivityThread . throwRemoteServiceException ( ActivityThread . java : 2219 )
at android . app . ActivityThread . - $$Nest$mthrowRemoteServiceException ( Unknown Source : 0 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 2505 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
* /
return false ;
2020-04-10 14:15:30 +00:00
if ( " android.view.WindowManager$BadTokenException " . equals ( ex . getClass ( ) . getName ( ) ) )
/ *
android . view . WindowManager$BadTokenException : Unable to add window - - token android . os . BinderProxy @e9084db is not valid ; is your activity running ?
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 827 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 356 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 93 )
at android . app . ActivityThread . handleResumeActivity ( ActivityThread . java : 4084 )
at android . app . servertransaction . ResumeActivityItem . execute ( ResumeActivityItem . java : 51 )
at android . app . servertransaction . TransactionExecutor . executeLifecycleState ( TransactionExecutor . java : 145 )
at android . app . servertransaction . TransactionExecutor . execute ( TransactionExecutor . java : 70 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 1976 )
* /
return false ;
2019-08-12 11:17:55 +00:00
if ( ex instanceof NoSuchMethodError )
2020-03-25 09:05:51 +00:00
/ *
java . lang . NoSuchMethodError : No direct method ( ) V in class Landroid / security / IKeyChainService$Stub ; or its super classes ( declaration of ' android . security . IKeyChainService$Stub ' appears in / system / framework / framework . jar ! classes2 . dex )
2020-08-06 11:52:27 +00:00
at com . android . keychain . KeyChainService$1 . ( KeyChainService . java : 95 )
at com . android . keychain . KeyChainService . ( KeyChainService . java : 95 )
at java . lang . Class . newInstance ( Native Method )
at android . app . AppComponentFactory . instantiateService ( AppComponentFactory . java : 103 )
2020-03-25 09:05:51 +00:00
* /
2019-08-12 11:17:55 +00:00
return false ;
2019-09-03 06:18:30 +00:00
if ( ex instanceof IllegalStateException & &
" Drag shadow dimensions must be positive " . equals ( ex . getMessage ( ) ) )
/ *
Android 9 only
java . lang . IllegalStateException : Drag shadow dimensions must be positive
java . lang . IllegalStateException : Drag shadow dimensions must be positive
2020-08-06 11:52:27 +00:00
at android . view . View . startDragAndDrop ( View . java : 24027 )
at android . widget . Editor . startDragAndDrop ( Editor . java : 1165 )
at android . widget . Editor . performLongClick ( Editor . java : 1191 )
at android . widget . TextView . performLongClick ( TextView . java : 11346 )
at android . view . View . performLongClick ( View . java : 6653 )
at android . view . View$CheckForLongPress . run ( View . java : 25855 )
at android . os . Handler . handleCallback ( Handler . java : 873 )
2019-09-03 06:18:30 +00:00
* /
return false ;
2020-06-26 19:44:52 +00:00
if ( ex instanceof IllegalStateException & &
" Results have already been set " . equals ( ex . getMessage ( ) ) )
/ *
Play billing ?
java . lang . IllegalStateException : Results have already been set
2020-08-06 11:52:27 +00:00
at Gu . a ( Unknown : 8 )
at Fq . a ( Unknown : 29 )
at Fk . b ( Unknown : 17 )
at Fk . a ( Unknown : 12 )
at Fk . b ( Unknown : 5 )
at Ex . a ( Unknown : 3 )
at Ep . b ( Unknown : 9 )
at Ep . a ( Unknown : 76 )
at Ep . a ( Unknown : 16 )
at GH . a ( Unknown : 2 )
at Gz . a ( Unknown : 48 )
at GC . handleMessage ( Unknown : 6 )
at android . os . Handler . dispatchMessage ( Handler . java : 108 )
at android . os . Looper . loop ( Looper . java : 166 )
at android . os . HandlerThread . run ( HandlerThread . java : 65 )
2020-06-26 19:44:52 +00:00
* /
return false ;
2020-03-19 16:54:17 +00:00
if ( ex instanceof IllegalArgumentException & &
ex . getCause ( ) instanceof RemoteException )
/ *
java . lang . IllegalArgumentException
at android . os . Parcel . createException ( Parcel . java : 1954 )
at android . os . Parcel . readException ( Parcel . java : 1918 )
at android . os . Parcel . readException ( Parcel . java : 1868 )
at android . view . IWindowSession$Stub$Proxy . addToDisplay ( IWindowSession . java : 826 )
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 758 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 356 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 93 )
at android . app . ActivityThread . handleResumeActivity ( ActivityThread . java : 3906 )
at android . app . servertransaction . ResumeActivityItem . execute ( ResumeActivityItem . java : 51 )
at android . app . servertransaction . TransactionExecutor . executeLifecycleState ( TransactionExecutor . java : 145 )
at android . app . servertransaction . TransactionExecutor . execute ( TransactionExecutor . java : 70 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 1816 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
at android . os . Looper . loop ( Looper . java : 193 )
at android . app . ActivityThread . main ( ActivityThread . java : 6718 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . RuntimeInit$MethodAndArgsCaller . run ( RuntimeInit . java : 491 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 858 )
Caused by : android . os . RemoteException : Remote stack trace :
at android . view . SurfaceControl . nativeCreate ( Native Method )
at android . view . SurfaceControl . < init > ( SurfaceControl . java : 630 )
at android . view . SurfaceControl . < init > ( SurfaceControl . java : 60 )
at android . view . SurfaceControl$Builder . build ( SurfaceControl . java : 386 )
at com . android . server . wm . WindowContainer . onParentSet ( WindowContainer . java : 184 )
* /
return false ;
2019-09-19 08:32:55 +00:00
if ( ex instanceof IllegalArgumentException & &
ex . getMessage ( ) ! = null & &
ex . getMessage ( ) . startsWith ( " Tmp detached view should be removed from RecyclerView before it can be recycled " ) )
/ *
Android 9 only ?
java . lang . IllegalArgumentException : Tmp detached view should be removed from RecyclerView before it can be recycled : ViewHolder { e3b70bd position = 0 id = 1 , oldPos = - 1 , pLpos : - 1 update tmpDetached no parent } androidx . recyclerview . widget . RecyclerView { f0fe5b1 VFED . . . . . . . . . . . ID 0 , 0 - 641 , 456 # 7f090293 app : id / rvAccount } , adapter : eu . faircode . email . AdapterNavAccount @9a6ea96 , layout : androidx . recyclerview . widget . LinearLayoutManager @d8fc617 , context : eu . faircode . email . ActivityView @82a6ec4
at androidx . recyclerview . widget . RecyclerView$Recycler . recycleViewHolderInternal ( SourceFile : 6435 )
at androidx . recyclerview . widget . RecyclerView . removeAnimatingView ( SourceFile : 1456 )
at androidx . recyclerview . widget . RecyclerView$ItemAnimatorRestoreListener . onAnimationFinished ( SourceFile : 12690 )
at androidx . recyclerview . widget . RecyclerView$ItemAnimator . dispatchAnimationFinished ( SourceFile : 13190 )
at androidx . recyclerview . widget . SimpleItemAnimator . dispatchChangeFinished ( SourceFile : 317 )
at androidx . recyclerview . widget . DefaultItemAnimator$8 . onAnimationEnd ( SourceFile : 391 )
at android . view . ViewPropertyAnimator$AnimatorEventListener . onAnimationEnd ( ViewPropertyAnimator . java : 1122 )
* /
return false ;
2020-07-09 06:19:34 +00:00
if ( ex instanceof IllegalArgumentException & &
" page introduces incorrect tiling " . equals ( ex . getMessage ( ) ) )
/ *
java . lang . IllegalArgumentException : page introduces incorrect tiling
at androidx . paging . PagedStorage . insertPage ( SourceFile : 545 )
at androidx . paging . PagedStorage . tryInsertPageAndTrim ( SourceFile : 504 )
at androidx . paging . TiledPagedList$1 . onPageResult ( SourceFile : 60 )
at androidx . paging . DataSource$LoadCallbackHelper$1 . run ( SourceFile : 324 )
at android . os . Handler . handleCallback ( Handler . java : 789 )
* /
return false ;
2021-05-26 17:28:49 +00:00
if ( ex instanceof IllegalArgumentException & &
" Can't interpolate between two incompatible pathData " . equals ( ex . getMessage ( ) ) )
/ *
java . lang . IllegalArgumentException : Can ' t interpolate between two incompatible pathData
at android . animation . AnimatorInflater$PathDataEvaluator . evaluate ( AnimatorInflater . java : 265 )
at android . animation . AnimatorInflater$PathDataEvaluator . evaluate ( AnimatorInflater . java : 262 )
at android . animation . KeyframeSet . getValue ( KeyframeSet . java : 210 )
at android . animation . PropertyValuesHolder . calculateValue ( PropertyValuesHolder . java : 1018 )
at android . animation . ValueAnimator . animateValue ( ValueAnimator . java : 1341 )
at android . animation . ObjectAnimator . animateValue ( ObjectAnimator . java : 986 )
at android . animation . ValueAnimator . animateBasedOnTime ( ValueAnimator . java : 1258 )
at android . animation . ValueAnimator . doAnimationFrame ( ValueAnimator . java : 1306 )
at android . animation . AnimationHandler . doAnimationFrame ( AnimationHandler . java : 146 )
at android . animation . AnimationHandler . - wrap2 ( AnimationHandler . java )
at android . animation . AnimationHandler$1 . doFrame ( AnimationHandler . java : 54 )
at android . view . Choreographer$CallbackRecord . run ( Choreographer . java : 925 )
at android . view . Choreographer . doCallbacks ( Choreographer . java : 702 )
at android . view . Choreographer . doFrame ( Choreographer . java : 635 )
at android . view . Choreographer$FrameDisplayEventReceiver . run ( Choreographer . java : 913 )
at android . os . Handler . handleCallback ( Handler . java : 751 )
* /
return false ;
2020-06-21 11:00:49 +00:00
if ( ex instanceof IllegalMonitorStateException )
/ *
java . lang . IllegalMonitorStateException
at java . util . concurrent . locks . AbstractQueuedSynchronizer$ConditionObject . signal ( AbstractQueuedSynchronizer . java : 1959 )
at java . util . concurrent . ScheduledThreadPoolExecutor$DelayedWorkQueue . take ( ScheduledThreadPoolExecutor . java : 1142 )
at java . util . concurrent . ScheduledThreadPoolExecutor$DelayedWorkQueue . take ( ScheduledThreadPoolExecutor . java : 849 )
at java . util . concurrent . ThreadPoolExecutor . getTask ( ThreadPoolExecutor . java : 1092 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . java : 1152 )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 641 )
at java . lang . Thread . run ( Thread . java : 764 )
* /
return false ;
2020-04-20 06:07:41 +00:00
if ( ex instanceof RuntimeException & &
ex . getCause ( ) instanceof TransactionTooLargeException )
// Some Android versions (Samsung) send images as clip data
return false ;
2019-12-05 12:25:59 +00:00
if ( ex instanceof RuntimeException & &
ex . getMessage ( ) ! = null & &
2021-01-31 11:25:10 +00:00
( ex . getMessage ( ) . startsWith ( " Could not get application info " ) | |
2020-03-25 09:05:51 +00:00
ex . getMessage ( ) . startsWith ( " Unable to create service " ) | |
2020-04-18 17:29:58 +00:00
ex . getMessage ( ) . startsWith ( " Unable to start service " ) | |
2020-04-16 06:19:13 +00:00
ex . getMessage ( ) . startsWith ( " Unable to resume activity " ) | |
2020-03-25 09:47:08 +00:00
ex . getMessage ( ) . startsWith ( " Failure delivering result " ) ) )
2019-12-05 12:25:59 +00:00
return false ;
2020-03-25 09:05:51 +00:00
/ *
2020-08-06 11:52:27 +00:00
java . lang . RuntimeException : Unable to unbind to service androidx . work . impl . background . systemjob . SystemJobService @291a412 with Intent { cmp = eu . faircode . email / androidx . work . impl . background . systemjob . SystemJobService } : java . lang . RuntimeException : android . os . DeadSystemException
at android . app . ActivityThread . handleUnbindService ( ActivityThread . java : 4352 )
2019-12-05 12:25:59 +00:00
java . lang . RuntimeException : Could not get application info .
2020-08-06 11:52:27 +00:00
at CH0 . a ( PG : 11 )
at org . chromium . content . browser . ChildProcessLauncherHelperImpl . a ( PG : 34 )
at Fn2 . run ( PG : 5 )
at android . os . Handler . handleCallback ( Handler . java : 874 )
at android . os . Handler . dispatchMessage ( Handler . java : 100 )
at android . os . Looper . loop ( Looper . java : 198 )
at android . os . HandlerThread . run ( HandlerThread . java : 65 )
2020-03-06 07:12:33 +00:00
java . lang . RuntimeException : Unable to create service eu . faircode . email . ServiceSynchronize : java . lang . NullPointerException : Attempt to invoke interface method ' java . util . List android . os . IUserManager . getProfiles ( int , boolean ) ' on a null object reference
at android . app . ActivityThread . handleCreateService ( ActivityThread . java : 2739 )
2020-03-25 09:05:51 +00:00
java . lang . RuntimeException : Failure delivering result ResultInfo { who = @android : autoFillAuth : , request = 2162688 , result = - 1 , data = Intent { ( has extras ) } } to activity { eu . faircode . email / eu . faircode . email . ActivitySetup } : java . lang . NullPointerException : Attempt to invoke interface method ' java . lang . Object java . util . List . get ( int ) ' on a null object reference
at android . app . ActivityThread . deliverResults ( ActivityThread . java : 4469 )
at android . app . ActivityThread . handleSendResult ( ActivityThread . java : 4511 )
at android . app . servertransaction . ActivityResultItem . execute ( ActivityResultItem . java : 49 )
at android . app . servertransaction . TransactionExecutor . executeCallbacks ( TransactionExecutor . java : 108 )
at android . app . servertransaction . TransactionExecutor . execute ( TransactionExecutor . java : 68 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 1821 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
at android . os . Looper . loop ( Looper . java : 193 )
at android . app . ActivityThread . main ( ActivityThread . java : 6874 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . RuntimeInit$MethodAndArgsCaller . run ( RuntimeInit . java : 493 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 861 )
Caused by : java . lang . NullPointerException : Attempt to invoke interface method ' java . lang . Object java . util . List . get ( int ) ' on a null object reference
at android . os . Parcel . createException ( Parcel . java : 1956 )
at android . os . Parcel . readException ( Parcel . java : 1918 )
at android . os . Parcel . readException ( Parcel . java : 1868 )
at android . view . autofill . IAutoFillManager$Stub$Proxy . setAuthenticationResult ( IAutoFillManager . java : 729 )
at android . view . autofill . AutofillManager . onAuthenticationResult ( AutofillManager . java : 1474 )
at android . app . Activity . dispatchActivityResult ( Activity . java : 7497 )
at android . app . ActivityThread . deliverResults ( ActivityThread . java : 4462 )
. . . 11 more
Caused by : android . os . RemoteException : Remote stack trace :
at com . android . server . autofill . Session . setAuthenticationResultLocked ( Session . java : 1005 )
at com . android . server . autofill . AutofillManagerServiceImpl . setAuthenticationResultLocked ( AutofillManagerServiceImpl . java : 325 )
at com . android . server . autofill . AutofillManagerService$AutoFillManagerServiceStub . setAuthenticationResult ( AutofillManagerService . java : 863 )
at android . view . autofill . IAutoFillManager$Stub . onTransact ( IAutoFillManager . java : 289 )
at android . os . Binder . execTransact ( Binder . java : 731 )
* /
2019-12-05 12:25:59 +00:00
2020-03-01 19:43:27 +00:00
if ( ex instanceof RuntimeException & &
" InputChannel is not initialized. " . equals ( ex . getMessage ( ) ) )
return false ;
2020-03-25 09:05:51 +00:00
/ *
2020-03-01 19:43:27 +00:00
java . lang . RuntimeException : InputChannel is not initialized .
at android . view . InputEventReceiver . nativeInit ( Native Method )
at android . view . InputEventReceiver . < init > ( InputEventReceiver . java : 72 )
at android . view . ViewRootImpl$WindowInputEventReceiver . < init > ( ViewRootImpl . java : 7612 )
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 957 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 387 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 96 )
at android . widget . Toast$TN . handleShow ( Toast . java : 514 )
at android . widget . Toast$TN$1 . handleMessage ( Toast . java : 417 )
at android . os . Handler . dispatchMessage ( Handler . java : 107 )
at android . os . Looper . loop ( Looper . java : 214 )
at android . app . ActivityThread . main ( ActivityThread . java : 7397 )
2020-03-25 09:05:51 +00:00
* /
2020-03-01 19:43:27 +00:00
2019-08-12 11:17:55 +00:00
if ( ex . getMessage ( ) ! = null & &
( ex . getMessage ( ) . startsWith ( " Bad notification posted " ) | |
ex . getMessage ( ) . contains ( " ActivityRecord not found " ) | |
2019-09-23 06:31:04 +00:00
ex . getMessage ( ) . startsWith ( " Unable to create layer " ) | |
2019-11-10 08:26:39 +00:00
ex . getMessage ( ) . startsWith ( " Illegal meta data value " ) | |
2019-11-17 11:49:54 +00:00
ex . getMessage ( ) . startsWith ( " Context.startForegroundService " ) | |
ex . getMessage ( ) . startsWith ( " PARAGRAPH span must start at paragraph boundary " ) ) )
2019-08-12 11:17:55 +00:00
return false ;
if ( ex instanceof TimeoutException & &
ex . getMessage ( ) ! = null & &
2019-09-19 08:32:55 +00:00
ex . getMessage ( ) . contains ( " finalize " ) )
2019-08-12 11:17:55 +00:00
return false ;
2022-12-13 19:33:40 +00:00
if ( " android.database.CursorWindowAllocationException " . equals ( ex . getClass ( ) . getName ( ) ) )
2020-06-04 05:27:18 +00:00
/ *
android . database . CursorWindowAllocationException : Could not allocate CursorWindow ' / data / user / 0 / eu . faircode . email / no_backup / androidx . work . workdb ' of size 2097152 due to error - 12 .
2020-08-06 11:52:27 +00:00
at android . database . CursorWindow . nativeCreate ( Native Method )
at android . database . CursorWindow . < init > ( CursorWindow . java : 139 )
at android . database . CursorWindow . < init > ( CursorWindow . java : 120 )
at android . database . AbstractWindowedCursor . clearOrCreateWindow ( AbstractWindowedCursor . java : 202 )
at android . database . sqlite . SQLiteCursor . fillWindow ( SQLiteCursor . java : 147 )
at android . database . sqlite . SQLiteCursor . getCount ( SQLiteCursor . java : 140 )
at android . database . AbstractCursor . moveToPosition ( AbstractCursor . java : 232 )
at android . database . AbstractCursor . moveToNext ( AbstractCursor . java : 281 )
at androidx . room . InvalidationTracker$1 . checkUpdatedTable ( SourceFile : 417 )
at androidx . room . InvalidationTracker$1 . run ( SourceFile : 388 )
at androidx . work . impl . utils . SerialExecutor$Task . run ( SourceFile : 91 )
2020-06-04 05:27:18 +00:00
* /
return false ;
2021-05-12 05:44:38 +00:00
if ( ex instanceof RuntimeException & &
2022-12-13 19:33:40 +00:00
ex . getCause ( ) ! = null & &
" android.database.CursorWindowAllocationException " . equals ( ex . getCause ( ) . getClass ( ) . getName ( ) ) )
2021-05-12 05:44:38 +00:00
/ *
java . lang . RuntimeException : Exception while computing database live data .
at androidx . room . RoomTrackingLiveData$1 . run ( SourceFile : 10 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . java : 1167 )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 641 )
at java . lang . Thread . run ( Thread . java : 764 )
Caused by : io . requery . android . database . CursorWindowAllocationException : Cursor window allocation of 2048 kb failed .
at io . requery . android . database . CursorWindow . < init > ( SourceFile : 7 )
at io . requery . android . database . CursorWindow . < init > ( SourceFile : 1 )
at io . requery . android . database . AbstractWindowedCursor . clearOrCreateWindow ( SourceFile : 2 )
at io . requery . android . database . sqlite . SQLiteCursor . fillWindow ( SourceFile : 1 )
at io . requery . android . database . sqlite . SQLiteCursor . getCount ( SourceFile : 2 )
at eu . faircode . email . DaoAttachment_Impl$14 . call ( SourceFile : 16 )
at eu . faircode . email . DaoAttachment_Impl$14 . call ( SourceFile : 1 )
at androidx . room . RoomTrackingLiveData$1 . run ( SourceFile : 7 )
* /
return false ;
2020-06-16 05:29:55 +00:00
if ( ex instanceof SQLiteFullException ) // database or disk is full (code 13 SQLITE_FULL)
return false ;
2020-06-04 05:27:18 +00:00
if ( " android.util.SuperNotCalledException " . equals ( ex . getClass ( ) . getName ( ) ) )
/ *
android . util . SuperNotCalledException : Activity { eu . faircode . email / eu . faircode . email . ActivityView } did not call through to super . onResume ( )
at android . app . Activity . performResume ( Activity . java : 7304 )
at android . app . ActivityThread . performNewIntents ( ActivityThread . java : 3165 )
at android . app . ActivityThread . handleNewIntent ( ActivityThread . java : 3180 )
at android . app . servertransaction . NewIntentItem . execute ( NewIntentItem . java : 49 )
* /
2020-05-08 18:14:34 +00:00
return false ;
2020-06-05 09:04:18 +00:00
if ( " android.view.WindowManager$InvalidDisplayException " . equals ( ex . getClass ( ) . getName ( ) ) )
/ *
android . view . WindowManager$InvalidDisplayException : Unable to add window android . view . ViewRootImpl$W @d7b5a0b - - the specified display can not be found
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 854 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 356 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 93 )
at android . widget . PopupWindow . invokePopup ( PopupWindow . java : 1492 )
at android . widget . PopupWindow . showAsDropDown ( PopupWindow . java : 1342 )
at androidx . appcompat . widget . AppCompatPopupWindow . showAsDropDown ( SourceFile : 77 )
at androidx . core . widget . PopupWindowCompat . showAsDropDown ( SourceFile : 69 )
at androidx . appcompat . widget . ListPopupWindow . show ( SourceFile : 754 )
at androidx . appcompat . view . menu . CascadingMenuPopup . showMenu ( SourceFile : 486 )
at androidx . appcompat . view . menu . CascadingMenuPopup . show ( SourceFile : 265 )
at androidx . appcompat . view . menu . MenuPopupHelper . showPopup ( SourceFile : 290 )
at androidx . appcompat . view . menu . MenuPopupHelper . tryShow ( SourceFile : 177 )
at androidx . appcompat . widget . ActionMenuPresenter$OpenOverflowRunnable . run ( SourceFile : 792 )
* /
return false ;
2020-08-07 16:26:30 +00:00
StackTraceElement [ ] stack = ex . getStackTrace ( ) ;
2020-11-18 13:27:21 +00:00
if ( ex instanceof IndexOutOfBoundsException & &
stack . length > 0 & &
2020-08-14 07:21:10 +00:00
" android.text.TextLine " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" measure " . equals ( stack [ 0 ] . getMethodName ( ) ) )
2020-08-07 16:26:30 +00:00
/ *
java . lang . IndexOutOfBoundsException : offset ( 21 ) should be less than line limit ( 20 )
at android . text . TextLine . measure ( Unknown Source : 233 )
at android . text . Layout . getHorizontal ( Unknown Source : 104 )
at android . text . Layout . getHorizontal ( Unknown Source : 4 )
at android . text . Layout . getPrimaryHorizontal ( Unknown Source : 4 )
at android . text . Layout . getPrimaryHorizontal ( Unknown Source : 1 )
at android . widget . Editor$ActionPinnedPopupWindow . computeLocalPosition ( Unknown Source : 275 )
at android . widget . Editor$PinnedPopupWindow . show ( Unknown Source : 15 )
at android . widget . Editor$ActionPinnedPopupWindow . show ( Unknown Source : 3 )
at android . widget . Editor$EmailAddPopupWindow . show ( Unknown Source : 92 )
at android . widget . Editor$1 . run ( Unknown Source : 6 )
at android . os . Handler . handleCallback ( Unknown Source : 2 )
* /
return false ;
2020-11-18 13:27:21 +00:00
if ( ex instanceof IllegalArgumentException & &
stack . length > 0 & &
2020-08-14 07:21:10 +00:00
" android.os.Parcel " . equals ( stack [ 0 ] . getClassName ( ) ) & &
( " createException " . equals ( stack [ 0 ] . getMethodName ( ) ) | |
" readException " . equals ( stack [ 0 ] . getMethodName ( ) ) ) )
2020-08-09 06:16:45 +00:00
/ *
java . lang . IllegalArgumentException
at android . os . Parcel . createException ( Parcel . java : 1954 )
at android . os . Parcel . readException ( Parcel . java : 1918 )
at android . os . Parcel . readException ( Parcel . java : 1868 )
at android . view . IWindowSession$Stub$Proxy . addToDisplay ( IWindowSession . java : 826 )
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 758 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 356 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 93 )
at android . app . ActivityThread . handleResumeActivity ( ActivityThread . java : 3906 )
java . lang . NullPointerException : Attempt to invoke virtual method ' int com . android . server . job . controllers . JobStatus . getUid ( ) ' on a null object reference
at android . os . Parcel . readException ( Parcel . java : 1605 )
at android . os . Parcel . readException ( Parcel . java : 1552 )
at android . app . job . IJobCallback$Stub$Proxy . jobFinished ( IJobCallback . java : 167 )
at android . app . job . JobService$JobHandler . handleMessage ( JobService . java : 147 )
at android . os . Handler . dispatchMessage ( Handler . java : 102 )
* /
return false ;
2020-11-18 13:27:21 +00:00
if ( ex instanceof NullPointerException & &
stack . length > 0 & &
2020-08-14 07:21:10 +00:00
" android.hardware.biometrics.BiometricPrompt " . equals ( stack [ 0 ] . getClassName ( ) ) )
2020-08-14 06:22:26 +00:00
/ *
java . lang . NullPointerException : Attempt to invoke virtual method ' java . lang . String android . hardware . fingerprint . FingerprintManager . getErrorString ( int , int ) ' on a null object reference
at android . hardware . biometrics . BiometricPrompt . lambda$sendError$0 ( BiometricPrompt . java : 490 )
at android . hardware . biometrics . - $$Lambda$BiometricPrompt$HqBGXtBUWNc - v8NoHYsj2gLfaRw . run ( Unknown Source : 6 )
at android . os . Handler . handleCallback ( Handler . java : 873 )
* /
return false ;
2020-11-18 13:27:21 +00:00
if ( ex instanceof NullPointerException & &
stack . length > 0 & &
" android.graphics.Rect " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" set " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
java . lang . NullPointerException : Attempt to read from field ' int android . graphics . Rect . left ' on a null object reference
at android . graphics . Rect . set ( Rect . java : 371 )
at android . view . InsetsState . readFromParcel ( InsetsState . java : 453 )
at android . view . IWindowSession$Stub$Proxy . addToDisplay ( IWindowSession . java : 1264 )
at android . view . ViewRootImpl . setView ( ViewRootImpl . java : 865 )
at android . view . WindowManagerGlobal . addView ( WindowManagerGlobal . java : 387 )
at android . view . WindowManagerImpl . addView ( WindowManagerImpl . java : 96 )
at android . app . ActivityThread . handleResumeActivity ( ActivityThread . java : 4297 )
* /
return false ;
2021-02-03 08:26:12 +00:00
if ( ex instanceof NullPointerException & &
stack . length > 0 & &
" android.app.ActivityThread " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" handleStopActivity " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
Android : 6 . 0 . 1
java . lang . NullPointerException : Attempt to read from field ' android . app . Activity android . app . ActivityThread$ActivityClientRecord . activity ' on a null object reference
at android . app . ActivityThread . handleStopActivity ( ActivityThread . java : 4766 )
at android . app . ActivityThread . access$1400 ( ActivityThread . java : 221 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 1823 )
at android . os . Handler . dispatchMessage ( Handler . java : 102 )
at android . os . Looper . loop ( Looper . java : 158 )
at android . app . ActivityThread . main ( ActivityThread . java : 7224 )
* /
return false ;
2021-12-29 16:47:07 +00:00
if ( ex instanceof NullPointerException & &
ex . getCause ( ) instanceof RemoteException )
/ *
java . lang . NullPointerException : Attempt to invoke virtual method ' boolean com . android . server . autofill . RemoteFillService$PendingRequest . cancel ( ) ' on a null object reference
at android . os . Parcel . createException ( Parcel . java : 1956 )
at android . os . Parcel . readException ( Parcel . java : 1918 )
at android . os . Parcel . readException ( Parcel . java : 1868 )
at android . app . IActivityManager$Stub$Proxy . reportAssistContextExtras ( IActivityManager . java : 7079 )
at android . app . ActivityThread . handleRequestAssistContextExtras ( ActivityThread . java : 3338 )
at android . app . ActivityThread$H . handleMessage ( ActivityThread . java : 1839 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
at android . os . Looper . loop ( Looper . java : 193 )
at android . app . ActivityThread . main ( ActivityThread . java : 6971 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . RuntimeInit$MethodAndArgsCaller . run ( RuntimeInit . java : 493 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 865 )
Caused by : android . os . RemoteException : Remote stack trace :
at com . android . server . autofill . RemoteFillService . cancelCurrentRequest ( RemoteFillService . java : 177 )
at com . android . server . autofill . Session . cancelCurrentRequestLocked ( Session . java : 465 )
at com . android . server . autofill . Session . access$1000 ( Session . java : 118 )
at com . android . server . autofill . Session$1 . onHandleAssistData ( Session . java : 322 )
at com . android . server . am . ActivityManagerService . reportAssistContextExtras ( ActivityManagerService . java : 14510 )
* /
return false ;
2020-11-18 13:27:21 +00:00
if ( ex instanceof IndexOutOfBoundsException & &
stack . length > 0 & &
" android.text.SpannableStringInternal " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" checkRange " . equals ( stack [ 0 ] . getMethodName ( ) ) )
2020-08-14 07:17:34 +00:00
/ *
java . lang . IndexOutOfBoundsException : setSpan ( - 1 . . . - 1 ) starts before 0
at android . text . SpannableStringInternal . checkRange ( SpannableStringInternal . java : 478 )
at android . text . SpannableStringInternal . setSpan ( SpannableStringInternal . java : 189 )
at android . text . SpannableStringInternal . setSpan ( SpannableStringInternal . java : 178 )
at android . text . SpannableString . setSpan ( SpannableString . java : 60 )
at android . text . Selection . setSelection ( Selection . java : 93 )
at android . text . Selection . setSelection ( Selection . java : 77 )
at android . widget . Editor$SelectionHandleView . updateSelection ( Editor . java : 5281 )
at android . widget . Editor$HandleView . positionAtCursorOffset ( Editor . java : 4676 )
at android . widget . Editor$SelectionHandleView . positionAtCursorOffset ( Editor . java : 5466 )
at android . widget . Editor$SelectionHandleView . positionAndAdjustForCrossingHandles ( Editor . java : 5528 )
at android . widget . Editor$SelectionHandleView . updatePosition ( Editor . java : 5458 )
at android . widget . Editor$HandleView . onTouchEvent ( Editor . java : 4989 )
at android . widget . Editor$SelectionHandleView . onTouchEvent ( Editor . java : 5472 )
at android . view . View . dispatchTouchEvent ( View . java : 12545 )
at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 3083 )
at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2741 )
at android . widget . PopupWindow$PopupDecorView . dispatchTouchEvent ( PopupWindow . java : 2407 )
at android . view . View . dispatchPointerEvent ( View . java : 12789 )
* /
return false ;
2020-11-09 10:42:35 +00:00
if ( ex instanceof IndexOutOfBoundsException ) {
for ( StackTraceElement ste : stack )
if ( " android.widget.NumberPicker$SetSelectionCommand " . equals ( ste . getClassName ( ) ) & &
" run " . equals ( ste . getMethodName ( ) ) )
return false ;
/ *
java . lang . IndexOutOfBoundsException : setSpan ( 2 . . . 2 ) ends beyond length 0
at android . text . SpannableStringBuilder . checkRange ( SpannableStringBuilder . java : 1265 )
at android . text . SpannableStringBuilder . setSpan ( SpannableStringBuilder . java : 684 )
at android . text . SpannableStringBuilder . setSpan ( SpannableStringBuilder . java : 677 )
at android . text . Selection . setSelection ( Selection . java : 76 )
at android . widget . TextView . semSetSelection ( TextView . java : 11550 )
at android . widget . EditText . setSelection ( EditText . java : 118 )
at android . widget . NumberPicker$SetSelectionCommand . run ( NumberPicker . java : 2246 )
at android . os . Handler . handleCallback ( Handler . java : 751 )
* /
}
2021-02-22 09:26:39 +00:00
if ( ex instanceof IndexOutOfBoundsException ) {
for ( StackTraceElement ste : stack )
if ( " android.graphics.Paint " . equals ( ste . getClassName ( ) ) & &
" getTextRunCursor " . equals ( ste . getMethodName ( ) ) )
return false ;
/ *
Android 6 . 0 . 1
java . lang . IndexOutOfBoundsException
at android . graphics . Paint . getTextRunCursor ( Paint . java : 2160 )
at android . graphics . Paint . getTextRunCursor ( Paint . java : 2112 )
at android . widget . Editor . getNextCursorOffset ( Editor . java : 924 )
at android . widget . Editor . access$4700 ( Editor . java : 126 )
at android . widget . Editor$SelectionEndHandleView . positionAndAdjustForCrossingHandles ( Editor . java : 4708 )
at android . widget . Editor$SelectionEndHandleView . updatePosition ( Editor . java : 4692 )
at android . widget . Editor$HandleView . onTouchEvent ( Editor . java : 4012 )
at android . widget . Editor$SelectionEndHandleView . onTouchEvent ( Editor . java : 4726 )
at android . view . View . dispatchTouchEvent ( View . java : 9377 )
at android . view . ViewGroup . dispatchTransformedTouchEvent ( ViewGroup . java : 2554 )
at android . view . ViewGroup . dispatchTouchEvent ( ViewGroup . java : 2255 )
at android . widget . PopupWindow$PopupDecorView . dispatchTouchEvent ( PopupWindow . java : 2015 )
at android . view . View . dispatchPointerEvent ( View . java : 9597 )
at android . view . ViewRootImpl$ViewPostImeInputStage . processPointerEvent ( ViewRootImpl . java : 4234 )
at android . view . ViewRootImpl$ViewPostImeInputStage . onProcess ( ViewRootImpl . java : 4100 )
at android . view . ViewRootImpl$InputStage . deliver ( ViewRootImpl . java : 3646 )
at android . view . ViewRootImpl$InputStage . onDeliverToNext ( ViewRootImpl . java : 3699 )
at android . view . ViewRootImpl$InputStage . forward ( ViewRootImpl . java : 3665 )
at android . view . ViewRootImpl$AsyncInputStage . forward ( ViewRootImpl . java : 3791 )
at android . view . ViewRootImpl$InputStage . apply ( ViewRootImpl . java : 3673 )
at android . view . ViewRootImpl$AsyncInputStage . apply ( ViewRootImpl . java : 3848 )
at android . view . ViewRootImpl$InputStage . deliver ( ViewRootImpl . java : 3646 )
at android . view . ViewRootImpl$InputStage . onDeliverToNext ( ViewRootImpl . java : 3699 )
at android . view . ViewRootImpl$InputStage . forward ( ViewRootImpl . java : 3665 )
at android . view . ViewRootImpl$InputStage . apply ( ViewRootImpl . java : 3673 )
at android . view . ViewRootImpl$InputStage . deliver ( ViewRootImpl . java : 3646 )
at android . view . ViewRootImpl . deliverInputEvent ( ViewRootImpl . java : 5926 )
at android . view . ViewRootImpl . doProcessInputEvents ( ViewRootImpl . java : 5900 )
at android . view . ViewRootImpl . enqueueInputEvent ( ViewRootImpl . java : 5861 )
at android . view . ViewRootImpl$WindowInputEventReceiver . onInputEvent ( ViewRootImpl . java : 6029 )
at android . view . InputEventReceiver . dispatchInputEvent ( InputEventReceiver . java : 185 )
at android . view . InputEventReceiver . nativeConsumeBatchedInputEvents ( Native Method )
at android . view . InputEventReceiver . consumeBatchedInputEvents ( InputEventReceiver . java : 176 )
at android . view . ViewRootImpl . doConsumeBatchedInput ( ViewRootImpl . java : 6000 )
at android . view . ViewRootImpl$ConsumeBatchedInputRunnable . run ( ViewRootImpl . java : 6052 )
at android . view . Choreographer$CallbackRecord . run ( Choreographer . java : 858 )
at android . view . Choreographer . doCallbacks ( Choreographer . java : 670 )
at android . view . Choreographer . doFrame ( Choreographer . java : 600 )
at android . view . Choreographer$FrameDisplayEventReceiver . run ( Choreographer . java : 844 )
at android . os . Handler . handleCallback ( Handler . java : 739 )
* /
}
2021-05-25 13:16:19 +00:00
if ( ex instanceof StringIndexOutOfBoundsException ) {
for ( StackTraceElement ste : stack )
if ( " android.widget.Editor$SuggestionsPopupWindow " . equals ( ste . getClassName ( ) ) & &
" highlightTextDifferences " . equals ( ste . getMethodName ( ) ) )
return false ;
/ *
Android 7 . 0 Samsung
java . lang . StringIndexOutOfBoundsException : length = 175 ; regionStart = 174 ; regionLength = 7
at java . lang . String . substring ( String . java : 1931 )
at android . widget . Editor$SuggestionsPopupWindow . highlightTextDifferences ( Editor . java : 4002 )
at android . widget . Editor$SuggestionsPopupWindow . updateSuggestions ( Editor . java : 3933 )
at android . widget . Editor$SuggestionsPopupWindow . show ( Editor . java : 3836 )
at android . widget . Editor . replace ( Editor . java : 428 )
at android . widget . Editor$3 . run ( Editor . java : 2362 )
at android . os . Handler . handleCallback ( Handler . java : 751 )
at android . os . Handler . dispatchMessage ( Handler . java : 95 )
at android . os . Looper . loop ( Looper . java : 154 )
at android . app . ActivityThread . main ( ActivityThread . java : 6780 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . ZygoteInit$MethodAndArgsCaller . run ( ZygoteInit . java : 1500 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 1390 )
* /
}
2020-11-18 13:27:21 +00:00
if ( ex instanceof IllegalArgumentException & &
stack . length > 0 & &
2020-09-26 05:53:56 +00:00
" android.text.method.WordIterator " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" checkOffsetIsValid " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
https : //issuetracker.google.com/issues/37068143
2020-09-26 08:22:23 +00:00
https : //android.googlesource.com/platform/frameworks/base/+/refs/heads/marshmallow-release/core/java/android/text/method/WordIterator.java
2020-09-26 05:53:56 +00:00
java . lang . IllegalArgumentException : Invalid offset : - 1 . Valid range is [ 0 , 1673 ]
at android . text . method . WordIterator . checkOffsetIsValid ( WordIterator . java : 380 )
at android . text . method . WordIterator . isBoundary ( WordIterator . java : 101 )
at android . widget . Editor$SelectionStartHandleView . positionAtCursorOffset ( Editor . java : 4287 )
at android . widget . Editor$HandleView . updatePosition ( Editor . java : 3735 )
at android . widget . Editor$PositionListener . onPreDraw ( Editor . java : 2512 )
at android . view . ViewTreeObserver . dispatchOnPreDraw ( ViewTreeObserver . java : 944 )
at android . view . ViewRootImpl . performTraversals ( ViewRootImpl . java : 2412 )
at android . view . ViewRootImpl . doTraversal ( ViewRootImpl . java : 1321 )
at android . view . ViewRootImpl$TraversalRunnable . run ( ViewRootImpl . java : 6763 )
at android . view . Choreographer$CallbackRecord . run ( Choreographer . java : 894 )
at android . view . Choreographer . doCallbacks ( Choreographer . java : 696 )
at android . view . Choreographer . doFrame ( Choreographer . java : 631 )
at android . view . Choreographer$FrameDisplayEventReceiver . run ( Choreographer . java : 880 )
at android . os . Handler . handleCallback ( Handler . java : 815 )
* /
return false ;
2021-05-24 09:11:57 +00:00
if ( ex instanceof IllegalArgumentException & & ex . getCause ( ) ! = null ) {
for ( StackTraceElement ste : ex . getCause ( ) . getStackTrace ( ) )
if ( " android.view.textclassifier.TextClassifierImpl " . equals ( ste . getClassName ( ) ) & &
" validateInput " . equals ( ste . getMethodName ( ) ) )
2021-06-01 05:52:30 +00:00
return true ;
2021-05-24 09:11:57 +00:00
/ *
java . lang . RuntimeException : An error occurred while executing doInBackground ( )
at android . os . AsyncTask$3 . done ( AsyncTask . java : 353 )
at java . util . concurrent . FutureTask . finishCompletion ( FutureTask . java : 383 )
at java . util . concurrent . FutureTask . setException ( FutureTask . java : 252 )
at java . util . concurrent . FutureTask . run ( FutureTask . java : 271 )
at android . os . AsyncTask$SerialExecutor$1 . run ( AsyncTask . java : 245 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . java : 1162 )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 636 )
at java . lang . Thread . run ( Thread . java : 764 )
Caused by : java . lang . IllegalArgumentException
at com . android . internal . util . Preconditions . checkArgument ( Preconditions . java : 33 )
at android . view . textclassifier . TextClassifierImpl . validateInput ( TextClassifierImpl . java : 484 )
at android . view . textclassifier . TextClassifierImpl . classifyText ( TextClassifierImpl . java : 144 )
at android . widget . SelectionActionModeHelper$TextClassificationHelper . classifyText ( SelectionActionModeHelper . java : 465 )
at android . widget . SelectionActionModeHelper . - android_widget_SelectionActionModeHelper - mthref - 1 ( SelectionActionModeHelper . java : 83 )
at android . widget . - $Lambda$tTszxdFZ0V9nXhnBpPsqeBMO0fw$5 . $m$0 ( Unknown : 4 )
at android . widget . - $Lambda$tTszxdFZ0V9nXhnBpPsqeBMO0fw$5 . get ( Unknown )
at android . widget . SelectionActionModeHelper$TextClassificationAsyncTask . doInBackground ( SelectionActionModeHelper . java : 366 )
at android . widget . SelectionActionModeHelper$TextClassificationAsyncTask . doInBackground ( SelectionActionModeHelper . java : 361 )
at android . os . AsyncTask$2 . call ( AsyncTask . java : 333 )
at java . util . concurrent . FutureTask . run ( FutureTask . java : 266 )
at android . os . AsyncTask$SerialExecutor$1 . run ( AsyncTask . java : 245 )
at java . util . concurrent . ThreadPoolExecutor . runWorker ( ThreadPoolExecutor . java : 1162 )
at java . util . concurrent . ThreadPoolExecutor$Worker . run ( ThreadPoolExecutor . java : 636 )
at java . lang . Thread . run ( Thread . java : 764 )
* /
}
2020-11-18 13:27:21 +00:00
if ( ex instanceof NullPointerException & &
stack . length > 0 & &
2020-10-10 05:40:41 +00:00
" view.AccessibilityInteractionController " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" applyAppScaleAndMagnificationSpecIfNeeded " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
java . lang . NullPointerException : Attempt to invoke virtual method ' void android . graphics . RectF . scale ( float ) ' on a null object reference
at android . view . AccessibilityInteractionController . applyAppScaleAndMagnificationSpecIfNeeded ( AccessibilityInteractionController . java : 872 )
at android . view . AccessibilityInteractionController . applyAppScaleAndMagnificationSpecIfNeeded ( AccessibilityInteractionController . java : 796 )
at android . view . AccessibilityInteractionController . updateInfosForViewportAndReturnFindNodeResult ( AccessibilityInteractionController . java : 924 )
at android . view . AccessibilityInteractionController . findAccessibilityNodeInfoByAccessibilityIdUiThread ( AccessibilityInteractionController . java : 345 )
at android . view . AccessibilityInteractionController . access$400 ( AccessibilityInteractionController . java : 75 )
at android . view . AccessibilityInteractionController$PrivateHandler . handleMessage ( AccessibilityInteractionController . java : 1393 )
at android . os . Handler . dispatchMessage ( Handler . java : 107 )
* /
return false ;
2021-01-02 18:29:00 +00:00
if ( ex instanceof NullPointerException ) {
for ( StackTraceElement ste : stack )
if ( " android.app.job.IJobCallback$Stub$Proxy " . equals ( ste . getClassName ( ) ) & &
" jobFinished " . equals ( ste . getMethodName ( ) ) )
return false ;
/ *
java . lang . NullPointerException : Attempt to invoke virtual method ' int com . android . server . job . controllers . JobStatus . getUid ( ) ' on a null object reference
at android . os . Parcel . readException ( Parcel . java : 1605 )
at android . os . Parcel . readException ( Parcel . java : 1552 )
at android . app . job . IJobCallback$Stub$Proxy . jobFinished ( IJobCallback . java : 167 )
at android . app . job . JobService$JobHandler . handleMessage ( JobService . java : 147 )
at android . os . Handler . dispatchMessage ( Handler . java : 111 )
at android . os . Looper . loop ( Looper . java : 207 )
at android . app . ActivityThread . main ( ActivityThread . java : 5697 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . ZygoteInit$MethodAndArgsCaller . run ( ZygoteInit . java : 905 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 766 )
* /
}
2020-11-24 08:49:18 +00:00
if ( ex instanceof IllegalStateException & &
stack . length > 0 & &
" android.database.sqlite.SQLiteSession " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" throwIfNoTransaction " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
java . lang . IllegalStateException : Cannot perform this operation because there is no current transaction .
at android . database . sqlite . SQLiteSession . throwIfNoTransaction ( SQLiteSession . java : 917 )
at android . database . sqlite . SQLiteSession . endTransaction ( SQLiteSession . java : 400 )
at android . database . sqlite . SQLiteDatabase . endTransaction ( SQLiteDatabase . java : 585 )
at androidx . sqlite . db . framework . FrameworkSQLiteDatabase . endTransaction ( SourceFile : 1 )
at androidx . room . RoomDatabase . endTransaction ( SourceFile : 1 )
at androidx . work . impl . WorkerWrapper . runWorker ( SourceFile : 66 )
at androidx . work . impl . WorkerWrapper . run ( SourceFile : 3 )
at androidx . work . impl . utils . SerialExecutor$Task . run ( SourceFile : 1 )
* /
return false ;
2020-12-02 18:42:33 +00:00
if ( ex instanceof IllegalArgumentException & &
stack . length > 0 & &
" android.widget.SmartSelectSprite " . equals ( stack [ 0 ] . getClassName ( ) ) & &
" startAnimation " . equals ( stack [ 0 ] . getMethodName ( ) ) )
/ *
java . lang . IllegalArgumentException : Center point is not inside any of the rectangles !
at android . widget . SmartSelectSprite . startAnimation ( SmartSelectSprite . java : 392 )
at android . widget . SelectionActionModeHelper . startSelectionActionModeWithSmartSelectAnimation ( SelectionActionModeHelper . java : 319 )
at android . widget . SelectionActionModeHelper . lambda$l1f1_V5lw6noQxI_3u11qF753Iw ( Unknown Source : 0 )
at android . widget . - $$Lambda$SelectionActionModeHelper$l1f1_V5lw6noQxI_3u11qF753Iw . accept ( Unknown Source : 4 )
at android . widget . SelectionActionModeHelper$TextClassificationAsyncTask . onPostExecute ( SelectionActionModeHelper . java : 910 )
at android . widget . SelectionActionModeHelper$TextClassificationAsyncTask . onPostExecute ( SelectionActionModeHelper . java : 864 )
at android . os . AsyncTask . finish ( AsyncTask . java : 695 )
at android . os . AsyncTask . access$600 ( AsyncTask . java : 180 )
at android . os . AsyncTask$InternalHandler . handleMessage ( AsyncTask . java : 712 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
* /
return false ;
2020-09-10 16:37:39 +00:00
if ( ex instanceof InflateException )
/ *
android . view . InflateException : Binary XML file line # 7 : Binary XML file line # 7 : Error inflating class < unknown >
Caused by : android . view . InflateException : Binary XML file line # 7 : Error inflating class < unknown >
Caused by : java . lang . reflect . InvocationTargetException
at java . lang . reflect . Constructor . newInstance0 ( Native Method )
at java . lang . reflect . Constructor . newInstance ( Constructor . java : 343 )
at android . view . LayoutInflater . createView ( LayoutInflater . java : 686 )
at android . view . LayoutInflater . createViewFromTag ( LayoutInflater . java : 829 )
at android . view . LayoutInflater . createViewFromTag ( LayoutInflater . java : 769 )
at android . view . LayoutInflater . rInflate ( LayoutInflater . java : 902 )
at android . view . LayoutInflater . rInflateChildren ( LayoutInflater . java : 863 )
at android . view . LayoutInflater . inflate ( LayoutInflater . java : 554 )
at android . view . LayoutInflater . inflate ( LayoutInflater . java : 461 )
* /
return false ;
2021-02-04 13:44:19 +00:00
for ( StackTraceElement ste : stack ) {
String clazz = ste . getClassName ( ) ;
2022-06-26 05:11:04 +00:00
if ( clazz ! = null & & clazz . startsWith ( " org.chromium. " ) )
/ *
android . content . res . Resources$NotFoundException :
at android . content . res . ResourcesImpl . getValue ( ResourcesImpl . java : 225 )
at android . content . res . Resources . getInteger ( Resources . java : 1192 )
at org . chromium . ui . base . DeviceFormFactor . a ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 105 )
at y8 . onCreateActionMode ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 744 )
at px . onCreateActionMode ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 36 )
at com . android . internal . policy . DecorView$ActionModeCallback2Wrapper . onCreateActionMode ( DecorView . java : 2722 )
at com . android . internal . policy . DecorView . startActionMode ( DecorView . java : 926 )
at com . android . internal . policy . DecorView . startActionModeForChild ( DecorView . java : 882 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . ViewGroup . startActionModeForChild ( ViewGroup . java : 1035 )
at android . view . View . startActionMode ( View . java : 7654 )
at org . chromium . content . browser . selection . SelectionPopupControllerImpl . B ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 31 )
at uh0 . a ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 1605 )
at Kk0 . i ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 259 )
at B6 . run ( chromium - TrichromeWebViewGoogle6432 . aab - stable - 500512534 : 454 )
at android . os . Handler . handleCallback ( Handler . java : 938 )
* /
2021-02-04 13:44:19 +00:00
return false ;
}
2021-02-19 06:17:52 +00:00
if ( ex instanceof SecurityException & &
ex . getMessage ( ) ! = null & &
ex . getMessage ( ) . contains ( " com.opera.browser " ) )
/ *
java . lang . SecurityException : Permission Denial : starting Intent { act = android . intent . action . VIEW dat = https : //tracking.dpd.de/... cmp=com.opera.browser/.leanplum.LeanplumCatchActivity (has extras) } from ProcessRecord{3d9efb1 6332:eu.faircode.email/u0a54} (pid=6332, uid=10054) not exported from uid 10113
at android . os . Parcel . readException ( Parcel . java : 1951 )
at android . os . Parcel . readException ( Parcel . java : 1897 )
at android . app . IActivityManager$Stub$Proxy . startActivity ( IActivityManager . java : 4430 )
at android . app . Instrumentation . execStartActivity ( Instrumentation . java : 1610 )
at android . app . ContextImpl . startActivity ( ContextImpl . java : 862 )
at android . app . ContextImpl . startActivity ( ContextImpl . java : 839 )
at android . view . textclassifier . TextClassification . lambda$ - android_view_textclassifier_TextClassification_5020 ( TextClassification . java : 166 )
at android . view . textclassifier . - $Lambda$mxr44OLodDKdoE5ddAZvMdsFssQ . $m$0 ( Unknown Source : 8 )
at android . view . textclassifier . - $Lambda$mxr44OLodDKdoE5ddAZvMdsFssQ . onClick ( Unknown Source : 0 )
at org . chromium . content . browser . selection . SelectionPopupControllerImpl . m ( chromium - SystemWebViewGoogle . aab - stable - 432415203 : 17 )
at y5 . onActionItemClicked ( chromium - SystemWebViewGoogle . aab - stable - 432415203 : 20 )
at Bn . onActionItemClicked ( chromium - SystemWebViewGoogle . aab - stable - 432415203 : 1 )
at com . android . internal . policy . DecorView$ActionModeCallback2Wrapper . onActionItemClicked ( DecorView . java : 2472 )
at com . android . internal . view . FloatingActionMode$3 . onMenuItemSelected ( FloatingActionMode . java : 101 )
at com . android . internal . view . menu . MenuBuilder . dispatchMenuItemSelected ( MenuBuilder . java : 761 )
at com . android . internal . view . menu . MenuItemImpl . invoke ( MenuItemImpl . java : 167 )
at com . android . internal . view . menu . MenuBuilder . performItemAction ( MenuBuilder . java : 908 )
at com . android . internal . view . menu . MenuBuilder . performItemAction ( MenuBuilder . java : 898 )
at com . android . internal . view . FloatingActionMode . lambda$ - com_android_internal_view_FloatingActionMode_5176 ( FloatingActionMode . java : 129 )
at com . android . internal . view . - $Lambda$IoKM3AcgDw3Ok5aFi0zlym2p3IA . $m$0 ( Unknown Source : 4 )
at com . android . internal . view . - $Lambda$IoKM3AcgDw3Ok5aFi0zlym2p3IA . onMenuItemClick ( Unknown Source : 0 )
at com . android . internal . widget . FloatingToolbar$FloatingToolbarPopup$2 . onClick ( FloatingToolbar . java : 423 )
at android . view . View . performClick ( View . java : 6320 )
at android . view . View$PerformClick . run ( View . java : 25087 )
* /
return false ;
2023-11-30 14:52:57 +00:00
if ( ex instanceof RuntimeException ) {
for ( StackTraceElement ste : stack )
if ( " android.app.job.JobService$JobHandler " . equals ( ste . getClassName ( ) ) & &
" handleMessage " . equals ( ste . getMethodName ( ) ) )
return false ;
/ *
java . lang . RuntimeException : java . lang . NullPointerException : Attempt to invoke virtual method ' int com . android . server . job . controllers . JobStatus . getUid ( ) ' on a null object reference
at android . app . job . JobService$JobHandler . handleMessage ( JobService . java : 139 )
at android . os . Handler . dispatchMessage ( Handler . java : 102 )
at android . os . Looper . loop ( Looper . java : 150 )
at android . app . ActivityThread . main ( ActivityThread . java : 5546 )
at java . lang . reflect . Method . invoke ( Native Method )
at com . android . internal . os . ZygoteInit$MethodAndArgsCaller . run ( ZygoteInit . java : 792 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 682 )
* /
}
2022-10-01 17:41:57 +00:00
2021-01-31 11:25:10 +00:00
if ( isDead ( ex ) )
return false ;
2019-08-12 11:17:55 +00:00
if ( BuildConfig . BETA_RELEASE )
return true ;
while ( ex ! = null ) {
2021-02-10 17:24:45 +00:00
for ( StackTraceElement ste : stack )
2019-08-12 11:17:55 +00:00
if ( ste . getClassName ( ) . startsWith ( BuildConfig . APPLICATION_ID ) )
return true ;
ex = ex . getCause ( ) ;
}
return false ;
}
2021-01-31 11:25:10 +00:00
private static boolean isDead ( Throwable ex ) {
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
/ *
java . lang . RuntimeException : Failure from system
at android . app . ContextImpl . bindServiceCommon ( ContextImpl . java : 1327 )
at android . app . ContextImpl . bindService ( ContextImpl . java : 1286 )
at android . content . ContextWrapper . bindService ( ContextWrapper . java : 604 )
at android . content . ContextWrapper . bindService ( ContextWrapper . java : 604 )
at hq . run ( PG : 15 )
at java . lang . Thread . run ( Thread . java : 818 )
Caused by : android . os . DeadObjectException
at android . os . BinderProxy . transactNative ( Native Method )
at android . os . BinderProxy . transact ( Binder . java : 503 )
at android . app . ActivityManagerProxy . bindService ( ActivityManagerNative . java : 3783 )
at android . app . ContextImpl . bindServiceCommon ( ContextImpl . java : 1317 )
* /
Throwable cause = ex ;
while ( cause ! = null ) {
if ( cause instanceof DeadObjectException )
return true ;
cause = cause . getCause ( ) ;
}
}
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . N ) {
Throwable cause = ex ;
while ( cause ! = null ) {
if ( cause instanceof DeadSystemException )
return true ;
cause = cause . getCause ( ) ;
}
}
return false ;
}
2019-12-06 07:50:46 +00:00
static String formatThrowable ( Throwable ex ) {
return formatThrowable ( ex , true ) ;
}
2020-09-21 06:13:20 +00:00
static String formatThrowable ( Throwable ex , boolean sanitize ) {
return formatThrowable ( ex , " " , sanitize ) ;
2019-12-06 07:50:46 +00:00
}
static String formatThrowable ( Throwable ex , String separator , boolean sanitize ) {
2020-10-30 07:44:02 +00:00
if ( ex = = null )
return null ;
2019-12-06 07:50:46 +00:00
if ( sanitize ) {
if ( ex instanceof MessageRemovedException )
return null ;
2019-12-06 08:00:31 +00:00
if ( ex instanceof AuthenticationFailedException & &
ex . getCause ( ) instanceof SocketException )
return null ;
2021-11-24 07:23:27 +00:00
if ( ex instanceof ProtocolException & &
ex . getCause ( ) instanceof InterruptedException )
return null ; // Interrupted waitIfIdle
2019-12-06 08:09:14 +00:00
if ( ex instanceof MessagingException & &
2021-08-06 10:23:16 +00:00
( " Not connected " . equals ( ex . getMessage ( ) ) | | // POP3
" connection failure " . equals ( ex . getMessage ( ) ) | |
2019-12-06 08:09:14 +00:00
" failed to create new store connection " . equals ( ex . getMessage ( ) ) ) )
return null ;
2019-12-06 07:50:46 +00:00
if ( ex instanceof MessagingException & &
ex . getCause ( ) instanceof ConnectionException & &
ex . getCause ( ) . getMessage ( ) ! = null & &
( ex . getCause ( ) . getMessage ( ) . contains ( " Read error " ) | |
2019-12-06 08:02:11 +00:00
ex . getCause ( ) . getMessage ( ) . contains ( " Write error " ) | |
2020-01-09 09:49:53 +00:00
ex . getCause ( ) . getMessage ( ) . contains ( " Unexpected end of ZLIB input stream " ) | |
2019-12-06 08:02:11 +00:00
ex . getCause ( ) . getMessage ( ) . contains ( " Socket is closed " ) ) )
2019-12-06 07:50:46 +00:00
return null ;
// javax.mail.MessagingException: AU3 BAD User is authenticated but not connected.;
// nested exception is:
// com.sun.mail.iap.BadCommandException: AU3 BAD User is authenticated but not connected.
// javax.mail.MessagingException: AU3 BAD User is authenticated but not connected.;
// nested exception is:
// com.sun.mail.iap.BadCommandException: AU3 BAD User is authenticated but not connected.
// at com.sun.mail.imap.IMAPFolder.logoutAndThrow(SourceFile:1156)
// at com.sun.mail.imap.IMAPFolder.open(SourceFile:1063)
// at com.sun.mail.imap.IMAPFolder.open(SourceFile:977)
// at eu.faircode.email.ServiceSynchronize.monitorAccount(SourceFile:890)
// at eu.faircode.email.ServiceSynchronize.access$1500(SourceFile:85)
// at eu.faircode.email.ServiceSynchronize$7$1.run(SourceFile:627)
// at java.lang.Thread.run(Thread.java:764)
// Caused by: com.sun.mail.iap.BadCommandException: AU3 BAD User is authenticated but not connected.
// at com.sun.mail.iap.Protocol.handleResult(SourceFile:415)
// at com.sun.mail.imap.protocol.IMAPProtocol.select(SourceFile:1230)
// at com.sun.mail.imap.IMAPFolder.open(SourceFile:1034)
if ( ex instanceof MessagingException & &
ex . getCause ( ) instanceof BadCommandException & &
ex . getCause ( ) . getMessage ( ) ! = null & &
ex . getCause ( ) . getMessage ( ) . contains ( " User is authenticated but not connected " ) )
return null ;
2022-05-11 12:45:10 +00:00
//if (ex instanceof MessagingException &&
// ex.getMessage() != null &&
// ex.getMessage().startsWith("OAuth refresh"))
// return null;
2022-05-11 12:28:09 +00:00
2019-12-06 07:50:46 +00:00
if ( ex instanceof IOException & &
ex . getCause ( ) instanceof MessageRemovedException )
return null ;
if ( ex instanceof ConnectionException )
return null ;
2019-12-09 07:37:08 +00:00
if ( ex instanceof StoreClosedException | |
2021-07-27 16:32:10 +00:00
ex instanceof FolderClosedException | |
ex instanceof FolderClosedIOException | |
ex instanceof OperationCanceledException )
2019-12-06 07:50:46 +00:00
return null ;
if ( ex instanceof IllegalStateException & &
2021-12-01 18:33:29 +00:00
( TOKEN_REFRESH_REQUIRED . equals ( ex . getMessage ( ) ) | |
2021-11-28 10:15:22 +00:00
" Not connected " . equals ( ex . getMessage ( ) ) | |
2019-12-06 07:50:46 +00:00
" This operation is not allowed on a closed folder " . equals ( ex . getMessage ( ) ) ) )
return null ;
}
2022-03-13 10:46:26 +00:00
if ( ex instanceof MailConnectException & &
ex . getCause ( ) instanceof SocketTimeoutException )
ex = new Throwable ( " No response received from email server " , ex ) ;
2022-12-13 21:23:09 +00:00
if ( ex . getMessage ( ) ! = null & & ex . getMessage ( ) . contains ( " Read timed out " ) )
ex = new Throwable ( " No response received from email server " , ex ) ;
2022-03-13 10:46:26 +00:00
if ( ex instanceof MessagingException & &
ex . getCause ( ) instanceof UnknownHostException )
ex = new Throwable ( " Email server address lookup failed " , ex ) ;
2019-12-06 07:50:46 +00:00
StringBuilder sb = new StringBuilder ( ) ;
if ( BuildConfig . DEBUG )
sb . append ( ex . toString ( ) ) ;
else
sb . append ( ex . getMessage ( ) = = null ? ex . getClass ( ) . getName ( ) : ex . getMessage ( ) ) ;
Throwable cause = ex . getCause ( ) ;
while ( cause ! = null ) {
if ( BuildConfig . DEBUG )
sb . append ( separator ) . append ( cause . toString ( ) ) ;
else
sb . append ( separator ) . append ( cause . getMessage ( ) = = null ? cause . getClass ( ) . getName ( ) : cause . getMessage ( ) ) ;
cause = cause . getCause ( ) ;
}
return sb . toString ( ) ;
}
2019-08-12 14:18:41 +00:00
static void writeCrashLog ( Context context , Throwable ex ) {
2022-04-30 20:35:45 +00:00
File file = new File ( context . getFilesDir ( ) , " crash.log " ) ;
2019-08-12 11:17:55 +00:00
Log . w ( " Writing exception to " + file ) ;
try ( FileWriter out = new FileWriter ( file , true ) ) {
2021-09-28 20:16:03 +00:00
out . write ( BuildConfig . VERSION_NAME + BuildConfig . REVISION + " " + new Date ( ) + " \ r \ n " ) ;
2019-08-12 11:17:55 +00:00
out . write ( ex + " \ r \ n " + android . util . Log . getStackTraceString ( ex ) + " \ r \ n " ) ;
} catch ( IOException e ) {
Log . e ( e ) ;
}
}
2023-06-18 06:38:22 +00:00
static EntityMessage getDebugInfo ( Context context , String source , int title , Throwable ex , String log , Bundle args ) throws IOException , JSONException {
2019-05-12 17:14:34 +00:00
StringBuilder sb = new StringBuilder ( ) ;
2023-06-18 06:38:22 +00:00
sb . append ( context . getString ( title ) ) . append ( " \ n \ n " ) ;
if ( args ! = null ) {
2023-07-09 06:21:21 +00:00
sb . append ( args . getString ( " issue " ) ) . append ( '\n' ) ;
if ( args . containsKey ( " account " ) )
sb . append ( '\n' ) . append ( " Account: " ) . append ( args . getString ( " account " ) ) ;
if ( args . containsKey ( " contact " ) )
sb . append ( '\n' ) . append ( " Prior contact: " ) . append ( args . getBoolean ( " contact " ) ) ;
2023-06-18 06:38:22 +00:00
}
sb . append ( " \ n \ n " ) ;
2019-05-12 17:14:34 +00:00
sb . append ( getAppInfo ( context ) ) ;
if ( ex ! = null )
sb . append ( ex . toString ( ) ) . append ( " \ n " ) . append ( android . util . Log . getStackTraceString ( ex ) ) ;
if ( log ! = null )
sb . append ( log ) ;
2021-08-15 19:28:33 +00:00
String body = " <pre class= \" fairemail_debug_info \" > " + TextUtils . htmlEncode ( sb . toString ( ) ) + " </pre> " ;
2019-05-12 17:14:34 +00:00
EntityMessage draft ;
DB db = DB . getInstance ( context ) ;
try {
db . beginTransaction ( ) ;
2019-09-23 08:04:46 +00:00
List < TupleIdentityEx > identities = db . identity ( ) . getComposableIdentities ( null ) ;
if ( identities = = null | | identities . size ( ) = = 0 )
2020-08-20 21:18:55 +00:00
throw new IllegalArgumentException ( context . getString ( R . string . title_no_composable ) ) ;
2019-09-23 08:04:46 +00:00
EntityIdentity identity = identities . get ( 0 ) ;
EntityFolder drafts = db . folder ( ) . getFolderByType ( identity . account , EntityFolder . DRAFTS ) ;
2020-11-24 20:28:42 +00:00
if ( drafts = = null )
throw new IllegalArgumentException ( context . getString ( R . string . title_no_drafts ) ) ;
2019-05-12 17:14:34 +00:00
draft = new EntityMessage ( ) ;
draft . account = drafts . account ;
draft . folder = drafts . id ;
2019-09-23 08:04:46 +00:00
draft . identity = identity . id ;
2019-05-12 17:14:34 +00:00
draft . msgid = EntityMessage . generateMessageId ( ) ;
draft . thread = draft . msgid ;
2023-10-08 20:50:16 +00:00
draft . from = new Address [ ] { new InternetAddress ( identity . email , identity . name , StandardCharsets . UTF_8 . name ( ) ) } ;
2019-05-12 17:14:34 +00:00
draft . to = new Address [ ] { myAddress ( ) } ;
2023-07-14 04:49:47 +00:00
draft . subject = context . getString ( R . string . app_name ) + " " + getVersionInfo ( context ) + " debug info - " + source ;
2019-05-12 17:14:34 +00:00
draft . received = new Date ( ) . getTime ( ) ;
draft . seen = true ;
draft . ui_seen = true ;
draft . id = db . message ( ) . insertMessage ( draft ) ;
2020-02-20 09:35:01 +00:00
File file = draft . getFile ( context ) ;
Helper . writeText ( file , body ) ;
2022-02-13 10:36:38 +00:00
db . message ( ) . setMessageContent ( draft . id , true , null , 0 , null , null ) ;
2019-05-12 17:14:34 +00:00
2019-07-21 18:09:55 +00:00
attachSettings ( context , draft . id , 1 ) ;
attachAccounts ( context , draft . id , 2 ) ;
attachNetworkInfo ( context , draft . id , 3 ) ;
attachLog ( context , draft . id , 4 ) ;
attachOperations ( context , draft . id , 5 ) ;
2021-06-18 06:37:11 +00:00
attachTasks ( context , draft . id , 6 ) ;
attachLogcat ( context , draft . id , 7 ) ;
2020-10-09 12:29:30 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . O )
2021-06-18 06:37:11 +00:00
attachNotificationInfo ( context , draft . id , 8 ) ;
2022-01-31 13:43:40 +00:00
attachEnvironment ( context , draft . id , 9 ) ;
2021-02-10 08:57:48 +00:00
//if (MessageClassifier.isEnabled(context))
2022-01-31 12:36:19 +00:00
// attachClassifierData(context, draft.id, 10);
2019-07-21 18:09:55 +00:00
EntityOperation . queue ( context , draft , EntityOperation . ADD ) ;
2019-05-12 17:14:34 +00:00
db . setTransactionSuccessful ( ) ;
} finally {
db . endTransaction ( ) ;
}
2019-06-19 10:23:17 +00:00
2019-12-09 18:44:27 +00:00
ServiceSynchronize . eval ( context , " debuginfo " ) ;
2019-12-07 19:32:58 +00:00
2019-05-12 17:14:34 +00:00
return draft ;
}
2023-02-10 07:34:31 +00:00
static void unexpectedError ( Fragment fragment , Throwable ex ) {
unexpectedError ( fragment , ex , true ) ;
}
static void unexpectedError ( Fragment fragment , Throwable ex , boolean report ) {
try {
unexpectedError ( fragment . getParentFragmentManager ( ) , ex , report ) ;
} catch ( Throwable exex ) {
Log . w ( exex ) ;
/ *
Exception java . lang . IllegalStateException :
at androidx . fragment . app . Fragment . getParentFragmentManager ( Fragment . java : 1107 )
at eu . faircode . email . FragmentDialogForwardRaw . send ( FragmentDialogForwardRaw . java : 307 )
at eu . faircode . email . FragmentDialogForwardRaw . access$200 ( FragmentDialogForwardRaw . java : 56 )
at eu . faircode . email . FragmentDialogForwardRaw$4 . onClick ( FragmentDialogForwardRaw . java : 239 )
at androidx . appcompat . app . AlertController$ButtonHandler . handleMessage ( AlertController . java : 167 )
at android . os . Handler . dispatchMessage ( Handler . java : 106 )
at android . os . Looper . loopOnce ( Looper . java : 210 )
at android . os . Looper . loop ( Looper . java : 299 )
at android . app . ActivityThread . main ( ActivityThread . java : 8168 )
at java . lang . reflect . Method . invoke ( Method . java )
at com . android . internal . os . RuntimeInit$MethodAndArgsCaller . run ( RuntimeInit . java : 556 )
at com . android . internal . os . ZygoteInit . main ( ZygoteInit . java : 1037 )
* /
}
}
2019-12-06 07:50:46 +00:00
static void unexpectedError ( FragmentManager manager , Throwable ex ) {
2020-07-15 07:54:27 +00:00
unexpectedError ( manager , ex , true ) ;
}
static void unexpectedError ( FragmentManager manager , Throwable ex , boolean report ) {
2023-12-06 10:06:33 +00:00
unexpectedError ( manager , ex , report , null ) ;
}
static void unexpectedError ( FragmentManager manager , Throwable ex , int faq ) {
unexpectedError ( manager , ex , false , faq ) ;
}
static void unexpectedError ( FragmentManager manager , Throwable ex , boolean report , Integer faq ) {
2019-12-06 07:50:46 +00:00
Log . e ( ex ) ;
2020-11-14 06:50:24 +00:00
if ( ex instanceof OutOfMemoryError )
report = false ;
2019-12-06 07:50:46 +00:00
Bundle args = new Bundle ( ) ;
args . putSerializable ( " ex " , ex ) ;
2020-07-15 07:54:27 +00:00
args . putBoolean ( " report " , report ) ;
2023-12-06 10:06:33 +00:00
args . putInt ( " faq " , faq = = null ? 0 : faq ) ;
2019-12-06 07:50:46 +00:00
FragmentDialogUnexpected fragment = new FragmentDialogUnexpected ( ) ;
fragment . setArguments ( args ) ;
fragment . show ( manager , " error:unexpected " ) ;
}
public static class FragmentDialogUnexpected extends FragmentDialogBase {
@NonNull
@Override
public Dialog onCreateDialog ( @Nullable Bundle savedInstanceState ) {
2023-12-06 10:06:33 +00:00
Bundle args = getArguments ( ) ;
final Throwable ex = ( Throwable ) args . getSerializable ( " ex " ) ;
final boolean report = args . getBoolean ( " report " , true ) ;
final int faq = args . getInt ( " faq " ) ;
2019-12-06 07:50:46 +00:00
2021-10-17 05:26:38 +00:00
final Context context = getContext ( ) ;
LayoutInflater inflater = LayoutInflater . from ( context ) ;
View dview = inflater . inflate ( R . layout . dialog_unexpected , null ) ;
TextView tvError = dview . findViewById ( R . id . tvError ) ;
2023-12-06 10:06:33 +00:00
Button btnHelp = dview . findViewById ( R . id . btnHelp ) ;
2021-10-17 05:26:38 +00:00
2022-04-06 06:26:27 +00:00
String message = Log . formatThrowable ( ex , false ) ;
tvError . setText ( message ) ;
2021-10-17 05:26:38 +00:00
2023-12-06 10:06:33 +00:00
btnHelp . setVisibility ( faq > 0 ? View . VISIBLE : View . GONE ) ;
btnHelp . setOnClickListener ( new View . OnClickListener ( ) {
@Override
public void onClick ( View v ) {
Helper . viewFAQ ( v . getContext ( ) , faq ) ;
}
} ) ;
2022-04-06 06:26:27 +00:00
AlertDialog . Builder builder = new AlertDialog . Builder ( context )
2021-10-17 05:26:38 +00:00
. setView ( dview )
2022-04-06 06:26:27 +00:00
. setNegativeButton ( android . R . string . cancel , null )
. setPositiveButton ( R . string . menu_faq , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialogInterface , int i ) {
2022-05-15 08:19:48 +00:00
Uri uri = Helper . getSupportUri ( context , " Unexpected:error " ) ;
2022-04-06 06:26:27 +00:00
if ( ! TextUtils . isEmpty ( message ) )
uri = uri
. buildUpon ( )
. appendQueryParameter ( " message " , " Unexpected: " + message )
. build ( ) ;
Helper . view ( context , uri , true ) ;
}
} ) ;
2020-07-15 07:54:27 +00:00
if ( report )
builder . setNeutralButton ( R . string . title_report , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
2020-10-30 09:36:16 +00:00
// Dialog will be dismissed
final Context context = getContext ( ) ;
2020-07-15 07:54:27 +00:00
new SimpleTask < Long > ( ) {
@Override
protected Long onExecute ( Context context , Bundle args ) throws Throwable {
2023-06-18 06:38:22 +00:00
return Log . getDebugInfo ( context , " report " , R . string . title_unexpected_info_remark , ex , null , null ) . id ;
2020-07-15 07:54:27 +00:00
}
@Override
protected void onExecuted ( Bundle args , Long id ) {
context . startActivity ( new Intent ( context , ActivityCompose . class )
. putExtra ( " action " , " edit " )
. putExtra ( " id " , id ) ) ;
}
@Override
protected void onException ( Bundle args , Throwable ex ) {
2023-12-06 16:06:46 +00:00
// Ignored
2020-07-15 07:54:27 +00:00
}
2020-10-30 09:36:16 +00:00
} . execute ( getContext ( ) , getActivity ( ) , new Bundle ( ) , " error:unexpected " ) ;
2020-07-15 07:54:27 +00:00
}
} ) ;
return builder . create ( ) ;
2019-12-06 07:50:46 +00:00
}
}
2023-07-14 04:49:47 +00:00
private static String getVersionInfo ( Context context ) {
return String . format ( " %s%s/%d%s%s%s \ r \ n " ,
BuildConfig . VERSION_NAME ,
BuildConfig . REVISION ,
Helper . hasValidFingerprint ( context ) ? 1 : 3 ,
BuildConfig . PLAY_STORE_RELEASE ? " p " : " " ,
BuildConfig . DEBUG ? " d " : " " ,
ActivityBilling . isPro ( context ) ? " + " : " - " ) ;
}
2019-05-12 17:14:34 +00:00
private static StringBuilder getAppInfo ( Context context ) {
StringBuilder sb = new StringBuilder ( ) ;
2021-08-23 16:03:34 +00:00
ContentResolver resolver = context . getContentResolver ( ) ;
2021-07-18 17:41:28 +00:00
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
2022-06-27 19:36:45 +00:00
boolean main_log = prefs . getBoolean ( " main_log " , true ) ;
2022-06-26 07:52:24 +00:00
boolean protocol = prefs . getBoolean ( " protocol " , false ) ;
2022-06-05 13:40:19 +00:00
long last_cleanup = prefs . getLong ( " last_cleanup " , 0 ) ;
2021-07-18 17:41:28 +00:00
2021-07-17 11:49:08 +00:00
PackageManager pm = context . getPackageManager ( ) ;
2021-12-14 08:17:52 +00:00
2019-05-12 17:14:34 +00:00
// Get version info
2023-07-14 04:49:47 +00:00
sb . append ( String . format ( " %s %s \ r \ n " , context . getString ( R . string . app_name ) , getVersionInfo ( context ) ) ) ;
2023-01-01 09:53:44 +00:00
sb . append ( String . format ( " Package: %s uid: %d \ r \ n " ,
BuildConfig . APPLICATION_ID , android . os . Process . myUid ( ) ) ) ;
2022-06-10 14:53:14 +00:00
sb . append ( String . format ( " Android: %s (SDK device=%d target=%d) \ r \ n " ,
Build . VERSION . RELEASE , Build . VERSION . SDK_INT , Helper . getTargetSdk ( context ) ) ) ;
2021-11-08 16:55:11 +00:00
2023-08-29 16:44:26 +00:00
String miui = Helper . getMIUIVersion ( ) ;
2023-08-30 16:45:07 +00:00
Integer autostart = ( miui = = null ? null : Helper . getMIUIAutostart ( context ) ) ;
sb . append ( String . format ( " MIUI: %s autostart: %s \ r \ n " ,
miui = = null ? " - " : miui ,
autostart = = null ? " ? " : Boolean . toString ( autostart = = 0 ) ) ) ;
2023-08-29 16:44:26 +00:00
2021-11-08 16:55:11 +00:00
boolean reporting = prefs . getBoolean ( " crash_reports " , false ) ;
2022-01-09 13:48:37 +00:00
if ( reporting | | BuildConfig . TEST_RELEASE ) {
2021-11-08 16:55:11 +00:00
String uuid = prefs . getString ( " uuid " , null ) ;
sb . append ( String . format ( " UUID: %s \ r \ n " , uuid = = null ? " - " : uuid ) ) ;
}
2023-10-31 08:23:47 +00:00
try {
ApplicationInfo app = pm . getApplicationInfo ( context . getPackageName ( ) , PackageManager . GET_META_DATA ) ;
String build_uuid = app . metaData . getString ( " com.bugsnag.android.BUILD_UUID " ) ;
sb . append ( String . format ( " Build UUID: %s \ r \ n " , build_uuid = = null ? " - " : build_uuid ) ) ;
} catch ( PackageManager . NameNotFoundException ex ) {
Log . e ( ex ) ;
}
2023-11-03 15:39:44 +00:00
String installer = Helper . getInstallerName ( context ) ;
2023-10-26 06:42:04 +00:00
sb . append ( String . format ( " Release: %s \ r \ n " , getReleaseType ( context ) ) ) ;
2023-08-05 06:55:50 +00:00
sb . append ( String . format ( " Play Store: %s \ r \ n " , Helper . hasPlayStore ( context ) ) ) ;
2023-11-03 15:39:44 +00:00
sb . append ( String . format ( " Installer: %s \ r \ n " , installer = = null ? " - " : installer ) ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Installed: %s \ r \ n " , new Date ( Helper . getInstallTime ( context ) ) ) ) ;
2022-07-20 20:10:07 +00:00
sb . append ( String . format ( " Updated: %s \ r \ n " , new Date ( Helper . getUpdateTime ( context ) ) ) ) ;
2022-06-05 13:40:19 +00:00
sb . append ( String . format ( " Last cleanup: %s \ r \ n " , new Date ( last_cleanup ) ) ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Now: %s \ r \ n " , new Date ( ) ) ) ;
2022-08-11 05:38:49 +00:00
sb . append ( String . format ( " Zone: %s \ r \ n " , TimeZone . getDefault ( ) . getID ( ) ) ) ;
2021-12-14 08:17:52 +00:00
2023-01-01 09:53:44 +00:00
String language = prefs . getString ( " language " , null ) ;
sb . append ( String . format ( " Locale: def=%s lang=%s \ r \ n " ,
Locale . getDefault ( ) , language ) ) ;
if ( Build . VERSION . SDK_INT < Build . VERSION_CODES . N )
sb . append ( String . format ( " System: %s \ r \ n " ,
Resources . getSystem ( ) . getConfiguration ( ) . locale ) ) ;
else {
LocaleList ll = Resources . getSystem ( ) . getConfiguration ( ) . getLocales ( ) ;
for ( int i = 0 ; i < ll . size ( ) ; i + + )
sb . append ( String . format ( " System: %s \ r \ n " , ll . get ( i ) ) ) ;
}
2019-05-12 17:14:34 +00:00
sb . append ( " \ r \ n " ) ;
2022-01-17 18:13:41 +00:00
String osVersion = null ;
try {
osVersion = System . getProperty ( " os.version " ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
2019-05-12 17:14:34 +00:00
// Get device info
sb . append ( String . format ( " Brand: %s \ r \ n " , Build . BRAND ) ) ;
sb . append ( String . format ( " Manufacturer: %s \ r \ n " , Build . MANUFACTURER ) ) ;
sb . append ( String . format ( " Model: %s \ r \ n " , Build . MODEL ) ) ;
sb . append ( String . format ( " Product: %s \ r \ n " , Build . PRODUCT ) ) ;
sb . append ( String . format ( " Device: %s \ r \ n " , Build . DEVICE ) ) ;
sb . append ( String . format ( " Host: %s \ r \ n " , Build . HOST ) ) ;
2021-11-03 07:01:23 +00:00
sb . append ( String . format ( " Time: %s \ r \ n " , new Date ( Build . TIME ) . toString ( ) ) ) ;
2019-05-12 17:14:34 +00:00
sb . append ( String . format ( " Display: %s \ r \ n " , Build . DISPLAY ) ) ;
sb . append ( String . format ( " Id: %s \ r \ n " , Build . ID ) ) ;
2022-01-09 17:02:08 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . S )
sb . append ( String . format ( " SoC: %s/%s \ r \ n " , Build . SOC_MANUFACTURER , Build . SOC_MODEL ) ) ;
2022-01-17 18:13:41 +00:00
sb . append ( String . format ( " OS version: %s \ r \ n " , osVersion ) ) ;
2019-05-12 17:14:34 +00:00
sb . append ( " \ r \ n " ) ;
2022-06-18 19:34:16 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . R ) {
try {
// https://developer.android.com/reference/android/app/ApplicationExitInfo
boolean exits = false ;
long from = new Date ( ) . getTime ( ) - 30 * 24 * 3600 * 1000L ;
ActivityManager am = Helper . getSystemService ( context , ActivityManager . class ) ;
List < ApplicationExitInfo > infos = am . getHistoricalProcessExitReasons (
context . getPackageName ( ) , 0 , 100 ) ;
for ( ApplicationExitInfo info : infos )
if ( info . getTimestamp ( ) > from & &
info . getImportance ( ) > = ActivityManager . RunningAppProcessInfo . IMPORTANCE_GONE ) {
exits = true ;
sb . append ( String . format ( " %s: %s \ r \ n " ,
new Date ( info . getTimestamp ( ) ) ,
2022-06-19 06:24:13 +00:00
Helper . getExitReason ( info . getReason ( ) ) ) ) ;
2022-06-18 19:34:16 +00:00
}
if ( ! exits )
sb . append ( " No crashes \ r \ n " ) ;
sb . append ( " \ r \ n " ) ;
} catch ( Throwable ex ) {
sb . append ( ex ) . append ( " \ r \ n " ) ;
}
}
2023-08-22 14:46:27 +00:00
sb . append ( String . format ( " Log main: %b protocol: %b debug: %b build: %b test: %b \ r \ n " ,
main_log , protocol , Log . isDebugLogLevel ( ) , BuildConfig . DEBUG , BuildConfig . TEST_RELEASE ) ) ;
2023-01-01 09:53:44 +00:00
2022-04-16 16:29:36 +00:00
int [ ] contacts = ContactInfo . getStats ( ) ;
sb . append ( String . format ( " Contact lookup: %d cached: %d \ r \ n " ,
contacts [ 0 ] , contacts [ 1 ] ) ) ;
2023-03-05 18:04:30 +00:00
sb . append ( String . format ( " Accessibility: %b \ r \ n " , Helper . isAccessibilityEnabled ( context ) ) ) ;
2022-04-16 16:29:36 +00:00
String charset = MimeUtility . getDefaultJavaCharset ( ) ;
sb . append ( String . format ( " Default charset: %s/%s \ r \ n " , charset , MimeUtility . mimeCharset ( charset ) ) ) ;
2023-09-21 07:12:39 +00:00
String emoji ;
try {
if ( EmojiCompat . isConfigured ( ) ) {
int emojiState = EmojiCompat . get ( ) . getLoadState ( ) ;
switch ( emojiState ) {
case EmojiCompat . LOAD_STATE_LOADING :
emoji = " Loading " ;
break ;
case EmojiCompat . LOAD_STATE_SUCCEEDED :
emoji = " Loaded " ;
break ;
case EmojiCompat . LOAD_STATE_FAILED :
emoji = " Failed " ;
break ;
case EmojiCompat . LOAD_STATE_DEFAULT :
emoji = " Not loaded " ;
break ;
default :
emoji = " ? " + emojiState ;
}
} else
emoji = " Disabled " ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
emoji = ex . toString ( ) ;
}
sb . append ( " Emoji: " ) . append ( emoji ) . append ( " \ r \ n " ) ;
2022-04-16 16:29:36 +00:00
sb . append ( " Transliterate: " )
. append ( TextHelper . canTransliterate ( ) )
. append ( " \ r \ n " ) ;
2023-01-11 09:44:14 +00:00
sb . append ( " Classifier: " )
. append ( Helper . humanReadableByteCount ( MessageClassifier . getSize ( context ) ) )
. append ( " \ r \ n " ) ;
2022-04-16 16:29:36 +00:00
sb . append ( " \ r \ n " ) ;
2022-06-14 13:55:11 +00:00
int cpus = Runtime . getRuntime ( ) . availableProcessors ( ) ;
sb . append ( String . format ( " Processors: %d \ r \ n " , cpus ) ) ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . N ) {
long running = SystemClock . uptimeMillis ( ) - android . os . Process . getStartUptimeMillis ( ) ;
long cpu = android . os . Process . getElapsedCpuTime ( ) ;
int util = ( int ) ( running = = 0 ? 0 : 100 * cpu / running / cpus ) ;
sb . append ( String . format ( " Uptime: %s CPU: %s %d%% \ r \ n " ,
Helper . formatDuration ( running ) , Helper . formatDuration ( cpu ) , util ) ) ;
}
2019-07-22 07:18:03 +00:00
2023-02-04 09:33:46 +00:00
Boolean largeHeap ;
try {
ApplicationInfo info = pm . getApplicationInfo ( context . getPackageName ( ) , 0 ) ;
largeHeap = ( info . flags & ApplicationInfo . FLAG_LARGE_HEAP ) ! = 0 ;
} catch ( Throwable ex ) {
largeHeap = null ;
}
2022-04-13 20:27:33 +00:00
ActivityManager am = Helper . getSystemService ( context , ActivityManager . class ) ;
2020-07-21 17:06:41 +00:00
ActivityManager . MemoryInfo mi = new ActivityManager . MemoryInfo ( ) ;
am . getMemoryInfo ( mi ) ;
2023-11-27 07:59:02 +00:00
sb . append ( String . format ( " Memory class: %d/%d Large: %s MB Total: %s Low: %b \ r \ n " ,
2023-02-04 09:33:46 +00:00
am . getMemoryClass ( ) , am . getLargeMemoryClass ( ) ,
largeHeap = = null ? " ? " : Boolean . toString ( largeHeap ) ,
2023-11-27 07:59:02 +00:00
Helper . humanReadableByteCount ( mi . totalMem ) ,
am . isLowRamDevice ( ) ) ) ;
2019-07-22 07:18:03 +00:00
2021-05-24 05:49:55 +00:00
long storage_available = Helper . getAvailableStorageSpace ( ) ;
long storage_total = Helper . getTotalStorageSpace ( ) ;
2022-05-01 05:52:49 +00:00
long storage_used = Helper . getSizeUsed ( context . getFilesDir ( ) ) ;
sb . append ( String . format ( " Storage space: %s/%s App: %s \ r \ n " ,
2021-05-24 05:49:55 +00:00
Helper . humanReadableByteCount ( storage_total - storage_available ) ,
Helper . humanReadableByteCount ( storage_total ) ,
2022-05-01 05:52:49 +00:00
Helper . humanReadableByteCount ( storage_used ) ) ) ;
long cache_used = Helper . getSizeUsed ( context . getCacheDir ( ) ) ;
long cache_quota = Helper . getCacheQuota ( context ) ;
sb . append ( String . format ( " Cache space: %s/%s \ r \ n " ,
Helper . humanReadableByteCount ( cache_used ) ,
Helper . humanReadableByteCount ( cache_quota ) ) ) ;
2019-10-19 19:53:19 +00:00
2019-07-22 07:18:03 +00:00
Runtime rt = Runtime . getRuntime ( ) ;
2021-08-31 05:40:08 +00:00
long hused = ( rt . totalMemory ( ) - rt . freeMemory ( ) ) / 1024L / 1024L ;
long hmax = rt . maxMemory ( ) / 1024L / 1024L ;
long nheap = Debug . getNativeHeapAllocatedSize ( ) / 1024L / 1024L ;
long nsize = Debug . getNativeHeapSize ( ) / 1024 / 1024L ;
sb . append ( String . format ( " Heap usage: %d/%d MiB native: %d/%d MiB \ r \ n " , hused , hmax , nheap , nsize ) ) ;
2019-07-22 07:18:03 +00:00
2021-09-07 15:08:00 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . R ) {
int ipc = IBinder . getSuggestedMaxIpcSizeBytes ( ) ;
sb . append ( String . format ( " IPC max: %s \ r \ n " , Helper . humanReadableByteCount ( ipc ) ) ) ;
}
2021-12-14 08:17:52 +00:00
sb . append ( " \ r \ n " ) ;
2022-04-13 20:27:33 +00:00
WindowManager wm = Helper . getSystemService ( context , WindowManager . class ) ;
2021-12-14 08:17:52 +00:00
Display display = wm . getDefaultDisplay ( ) ;
Point dim = new Point ( ) ;
display . getSize ( dim ) ;
float density = context . getResources ( ) . getDisplayMetrics ( ) . density ;
2022-03-09 12:26:16 +00:00
sb . append ( String . format ( " Density 1dp=%f \ r \ n " , density ) ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Resolution: %.2f x %.2f dp \ r \ n " , dim . x / density , dim . y / density ) ) ;
2021-08-10 07:23:05 +00:00
Configuration config = context . getResources ( ) . getConfiguration ( ) ;
2021-12-14 08:17:52 +00:00
2021-08-10 07:23:05 +00:00
String size ;
if ( config . isLayoutSizeAtLeast ( Configuration . SCREENLAYOUT_SIZE_XLARGE ) )
2021-12-14 08:17:52 +00:00
size = " XLarge " ;
2021-08-10 07:23:05 +00:00
else if ( config . isLayoutSizeAtLeast ( Configuration . SCREENLAYOUT_SIZE_LARGE ) )
2021-12-14 08:17:52 +00:00
size = " Large " ;
2021-08-10 07:23:05 +00:00
else if ( config . isLayoutSizeAtLeast ( Configuration . SCREENLAYOUT_SIZE_NORMAL ) )
2021-12-14 08:17:52 +00:00
size = " Medium " ;
2021-08-10 07:23:05 +00:00
else if ( config . isLayoutSizeAtLeast ( Configuration . SCREENLAYOUT_SIZE_SMALL ) )
2021-12-14 08:17:52 +00:00
size = " Small " ;
2021-08-10 07:23:05 +00:00
else
2021-12-14 08:17:52 +00:00
size = " size= " + ( config . screenLayout & Configuration . SCREENLAYOUT_SIZE_MASK ) ;
String orientation ;
if ( config . orientation = = Configuration . ORIENTATION_LANDSCAPE )
orientation = " Landscape " ;
else if ( config . orientation = = Configuration . ORIENTATION_PORTRAIT )
orientation = " Portrait " ;
else
orientation = " orientation= " + config . orientation ;
sb . append ( String . format ( " %s %s \ r \ n " , size , orientation ) ) ;
2019-05-12 17:14:34 +00:00
2021-08-23 16:03:34 +00:00
try {
float animation_scale = Settings . Global . getFloat ( resolver ,
Settings . Global . WINDOW_ANIMATION_SCALE , 0f ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Animation scale: %f %s \ r \ n " , animation_scale ,
animation_scale = = 1f ? " " : " !!! " ) ) ;
2021-08-23 16:03:34 +00:00
} catch ( Throwable ex ) {
2021-12-14 08:17:52 +00:00
sb . append ( ex ) . append ( " \ r \ n " ) ;
2021-08-23 16:03:34 +00:00
}
2021-06-05 06:47:26 +00:00
int uiMode = context . getResources ( ) . getConfiguration ( ) . uiMode ;
sb . append ( String . format ( " UI mode: 0x " ) )
. append ( Integer . toHexString ( uiMode ) )
2021-07-12 22:34:10 +00:00
. append ( " night= " ) . append ( Helper . isNight ( context ) )
2021-06-05 06:47:26 +00:00
. append ( " \ r \ n " ) ;
2021-12-14 08:17:52 +00:00
String uiType = Helper . getUiModeType ( context ) ;
sb . append ( String . format ( " UI type: %s %s \ r \ n " , uiType ,
" normal " . equals ( uiType ) ? " " : " !!! " ) ) ;
2021-10-02 05:37:00 +00:00
2022-06-11 11:14:28 +00:00
sb . append ( String . format ( " Darken support: %b \ r \ n " ,
2022-06-15 16:10:01 +00:00
WebViewEx . isFeatureSupported ( context , WebViewFeature . ALGORITHMIC_DARKENING ) ) ) ;
2022-06-30 06:02:41 +00:00
try {
PackageInfo pkg = WebViewCompat . getCurrentWebViewPackage ( context ) ;
2023-03-10 18:09:37 +00:00
sb . append ( String . format ( " WebView %d/%s \ r \ n " ,
2022-06-30 06:02:41 +00:00
pkg = = null ? - 1 : pkg . versionCode ,
2023-03-10 18:09:37 +00:00
pkg = = null ? null : pkg . versionName ) ) ;
2022-06-30 06:02:41 +00:00
} catch ( Throwable ex ) {
sb . append ( ex ) . append ( " \ r \ n " ) ;
}
2022-06-10 11:49:19 +00:00
2021-12-14 08:17:52 +00:00
sb . append ( " \ r \ n " ) ;
2021-05-15 12:06:44 +00:00
2021-08-07 07:42:52 +00:00
Boolean ignoring = Helper . isIgnoringOptimizations ( context ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Battery optimizations: %s %s \ r \ n " ,
ignoring = = null ? null : Boolean . toString ( ! ignoring ) ,
Boolean . FALSE . equals ( ignoring ) ? " !!! " : " " ) ) ;
2021-08-07 07:42:52 +00:00
2022-04-13 20:27:33 +00:00
PowerManager power = Helper . getSystemService ( context , PowerManager . class ) ;
2022-01-17 17:43:13 +00:00
boolean psaving = power . isPowerSaveMode ( ) ;
sb . append ( String . format ( " Battery saving: %s %s \ r \ n " , psaving , psaving ? " !!! " : " " ) ) ;
2021-08-15 19:11:47 +00:00
sb . append ( String . format ( " Charging: %b; level: %d \ r \ n " ,
Helper . isCharging ( context ) , Helper . getBatteryLevel ( context ) ) ) ;
2019-05-12 17:14:34 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . P ) {
2022-01-31 15:22:58 +00:00
// https://developer.android.com/reference/android/app/usage/UsageStatsManager
2022-04-13 20:27:33 +00:00
UsageStatsManager usm = Helper . getSystemService ( context , UsageStatsManager . class ) ;
2019-05-12 17:14:34 +00:00
int bucket = usm . getAppStandbyBucket ( ) ;
2021-08-18 18:43:25 +00:00
boolean inactive = usm . isAppInactive ( BuildConfig . APPLICATION_ID ) ;
2022-01-31 12:44:42 +00:00
sb . append ( String . format ( " Standby bucket: %d-%b-%s %s \ r \ n " ,
bucket , inactive , Helper . getStandbyBucketName ( bucket ) ,
2022-02-01 07:28:03 +00:00
( bucket < = UsageStatsManager . STANDBY_BUCKET_ACTIVE & & ! inactive ? " " : " !!! " ) ) ) ;
2019-05-12 17:14:34 +00:00
}
2021-12-14 08:17:52 +00:00
boolean canExact = AlarmManagerCompatEx . canScheduleExactAlarms ( context ) ;
boolean hasExact = AlarmManagerCompatEx . hasExactAlarms ( context ) ;
sb . append ( String . format ( " ExactAlarms can=%b has=%b %s \ r \ n " , canExact , hasExact ,
canExact ? " " : " !!! " ) ) ;
2021-04-05 15:30:47 +00:00
2021-12-14 08:17:52 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . P ) {
boolean restricted = am . isBackgroundRestricted ( ) ;
sb . append ( String . format ( " Background restricted: %b %s \ r \ n " , restricted ,
restricted ? " !!! " : " " ) ) ;
}
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . N ) {
boolean saving = ConnectionHelper . isDataSaving ( context ) ;
sb . append ( String . format ( " Data saving: %b %s \ r \ n " , saving ,
saving ? " !!! " : " " ) ) ;
}
2019-05-12 17:14:34 +00:00
2021-08-23 16:03:34 +00:00
try {
int finish_activities = Settings . Global . getInt ( resolver ,
Settings . Global . ALWAYS_FINISH_ACTIVITIES , 0 ) ;
2021-12-14 08:17:52 +00:00
sb . append ( String . format ( " Always finish: %d %s \ r \ n " , finish_activities ,
finish_activities = = 0 ? " " : " !!! " ) ) ;
2021-08-23 16:03:34 +00:00
} catch ( Throwable ex ) {
2021-12-14 08:17:52 +00:00
sb . append ( ex ) . append ( " \ r \ n " ) ;
2021-08-23 16:03:34 +00:00
}
2021-12-14 08:17:52 +00:00
sb . append ( " \ r \ n " ) ;
2021-08-30 10:06:18 +00:00
2019-05-12 17:14:34 +00:00
return sb ;
}
2022-01-31 14:08:59 +00:00
private static void attachSettings ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " settings.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2019-05-12 17:14:34 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
Map < String , ? > settings = prefs . getAll ( ) ;
List < String > keys = new ArrayList < > ( settings . keySet ( ) ) ;
Collections . sort ( keys ) ;
2022-03-07 07:21:19 +00:00
for ( String key : keys ) {
Object value = settings . get ( key ) ;
if ( " wipe_mnemonic " . equals ( key ) & & value ! = null )
value = " [redacted] " ;
2023-01-12 16:33:16 +00:00
else if ( " cloud_user " . equals ( key ) & & value ! = null )
value = " [redacted] " ;
else if ( " cloud_password " . equals ( key ) & & value ! = null )
value = " [redacted] " ;
2023-02-01 17:09:33 +00:00
else if ( " pin " . equals ( key ) & & value ! = null )
value = " [redacted] " ;
2023-01-12 16:33:16 +00:00
else if ( key ! = null & & key . startsWith ( " oauth. " ) )
2022-04-09 05:59:24 +00:00
value = " [redacted] " ;
2023-06-13 05:45:23 +00:00
else if ( key ! = null & & key . startsWith ( " graph.contacts. " ) )
value = " [redacted] " ;
2022-03-07 07:21:19 +00:00
size + = write ( os , key + " = " + value + " \ r \ n " ) ;
}
2022-05-12 09:09:57 +00:00
size + = write ( os , " \ r \ n " ) ;
try {
List < String > names = new ArrayList < > ( ) ;
Properties props = System . getProperties ( ) ;
Enumeration < ? > pnames = props . propertyNames ( ) ;
while ( pnames . hasMoreElements ( ) )
names . add ( ( String ) pnames . nextElement ( ) ) ;
Collections . sort ( names ) ;
for ( String name : names )
size + = write ( os , name + " = " + props . getProperty ( name ) + " \ r \ n " ) ;
} catch ( Throwable ex ) {
size + = write ( os , ex . getMessage ( ) + " \ r \ n " ) ;
}
2022-01-31 14:08:59 +00:00
}
2019-09-28 16:36:07 +00:00
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
2019-05-12 17:14:34 +00:00
}
2022-01-31 14:08:59 +00:00
private static void attachAccounts ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
2019-05-12 17:14:34 +00:00
2022-01-31 14:08:59 +00:00
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " accounts.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2021-06-17 19:25:51 +00:00
2022-01-31 14:08:59 +00:00
DateFormat dtf = Helper . getDateTimeInstance ( context , SimpleDateFormat . SHORT , SimpleDateFormat . SHORT ) ;
2021-06-17 19:25:51 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
List < EntityAccount > accounts = db . account ( ) . getAccounts ( ) ;
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
boolean enabled = prefs . getBoolean ( " enabled " , true ) ;
int pollInterval = ServiceSynchronize . getPollInterval ( context ) ;
boolean metered = prefs . getBoolean ( " metered " , true ) ;
Boolean ignoring = Helper . isIgnoringOptimizations ( context ) ;
2022-03-19 20:21:53 +00:00
boolean canSchedule = AlarmManagerCompatEx . canScheduleExactAlarms ( context ) ;
2022-01-31 14:08:59 +00:00
boolean auto_optimize = prefs . getBoolean ( " auto_optimize " , false ) ;
boolean schedule = prefs . getBoolean ( " schedule " , false ) ;
2022-04-03 11:16:32 +00:00
String ds = ConnectionHelper . getDataSaving ( context ) ;
2022-01-31 14:08:59 +00:00
boolean vpn = ConnectionHelper . vpnActive ( context ) ;
2023-03-19 08:14:33 +00:00
boolean ng = false ;
try {
PackageManager pm = context . getPackageManager ( ) ;
pm . getPackageInfo ( " eu.faircode.netguard " , 0 ) ;
ng = true ;
} catch ( Throwable ignored ) {
}
2022-01-31 14:08:59 +00:00
2022-06-19 06:14:22 +00:00
Integer bucket = null ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . P )
try {
UsageStatsManager usm = Helper . getSystemService ( context , UsageStatsManager . class ) ;
bucket = usm . getAppStandbyBucket ( ) ;
} catch ( Throwable ignored ) {
}
2022-07-29 16:21:20 +00:00
Integer filter = null ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
NotificationManager nm = Helper . getSystemService ( context , NotificationManager . class ) ;
filter = nm . getCurrentInterruptionFilter ( ) ;
}
2023-03-04 10:30:48 +00:00
StringBuilder filters = new StringBuilder ( ) ;
2023-03-05 18:46:43 +00:00
StringBuilder sorts = new StringBuilder ( ) ;
2023-03-04 10:30:48 +00:00
for ( String key : prefs . getAll ( ) . keySet ( ) )
if ( key . startsWith ( " filter_ " ) ) {
Object value = prefs . getAll ( ) . get ( key ) ;
if ( Boolean . TRUE . equals ( value ) )
2023-03-05 18:46:43 +00:00
filters . append ( ' ' ) . append ( key . substring ( 7 ) ) . append ( '=' ) . append ( value ) ;
} else if ( key . startsWith ( " sort_ " ) ) {
Object value = prefs . getAll ( ) . get ( key ) ;
sorts . append ( ' ' ) . append ( key ) . append ( '=' ) . append ( value ) ;
2023-03-04 10:30:48 +00:00
}
2022-01-31 14:08:59 +00:00
size + = write ( os , " enabled= " + enabled + ( enabled ? " " : " !!! " ) +
" interval= " + pollInterval + " \ r \ n " +
" metered= " + metered + ( metered ? " " : " !!! " ) +
2022-09-08 05:27:53 +00:00
" saving= " + ds + ( " enabled " . equals ( ds ) ? " !!! " : " " ) +
2022-02-22 07:48:37 +00:00
" vpn= " + vpn + ( vpn ? " !!! " : " " ) +
2023-03-19 08:14:33 +00:00
" ng= " + ng + " \ r \ n " +
2022-01-31 14:08:59 +00:00
" optimizing= " + ( ignoring = = null ? null : ! ignoring ) + ( Boolean . FALSE . equals ( ignoring ) ? " !!! " : " " ) +
2022-07-29 16:21:20 +00:00
" bucket= " + ( bucket = = null ? null :
Helper . getStandbyBucketName ( bucket ) +
( bucket > UsageStatsManager . STANDBY_BUCKET_ACTIVE ? " !!! " : " " ) ) +
2022-03-19 20:21:53 +00:00
" canSchedule= " + canSchedule + ( canSchedule ? " " : " !!! " ) +
2022-07-29 16:21:20 +00:00
" auto_optimize= " + auto_optimize + ( auto_optimize ? " !!! " : " " ) +
" notifications= " + ( filter = = null ? null :
Helper . getInterruptionFilter ( filter ) +
2023-09-02 09:39:14 +00:00
( filter = = NotificationManager . INTERRUPTION_FILTER_ALL ? " " : " !!! " ) ) + " \ r \ n " +
2022-01-31 14:08:59 +00:00
" accounts= " + accounts . size ( ) +
2023-07-06 09:11:40 +00:00
" folders= " + db . folder ( ) . countSync ( ) + " / " + db . folder ( ) . countTotal ( ) +
2022-01-31 14:08:59 +00:00
" messages= " + db . message ( ) . countTotal ( ) +
" rules= " + db . rule ( ) . countTotal ( ) +
2022-03-20 06:44:12 +00:00
" ops= " + db . operation ( ) . getOperationCount ( ) +
2023-03-04 10:30:48 +00:00
" outbox= " + db . message ( ) . countOutbox ( ) + " \ r \ n " +
2023-03-05 18:46:43 +00:00
" filter " + filters + " " + sorts +
2022-01-31 14:08:59 +00:00
" \ r \ n \ r \ n " ) ;
2021-08-08 11:55:45 +00:00
2022-01-31 14:08:59 +00:00
if ( schedule ) {
int minuteStart = prefs . getInt ( " schedule_start " , 0 ) ;
int minuteEnd = prefs . getInt ( " schedule_end " , 0 ) ;
2023-04-15 15:56:41 +00:00
int minuteStartWeekend = prefs . getInt ( " schedule_start_weekend " , minuteStart ) ;
int minuteEndWeekend = prefs . getInt ( " schedule_end_weekend " , minuteEnd ) ;
2022-01-31 14:08:59 +00:00
2023-03-12 09:15:38 +00:00
size + = write ( os , String . format ( " schedule %s...%s weekend %s...%s \ r \ n " ,
CalendarHelper . formatHour ( context , minuteStart ) ,
CalendarHelper . formatHour ( context , minuteEnd ) ,
CalendarHelper . formatHour ( context , minuteStartWeekend ) ,
CalendarHelper . formatHour ( context , minuteEndWeekend ) ) ) ;
2022-01-31 14:08:59 +00:00
String [ ] daynames = new DateFormatSymbols ( ) . getWeekdays ( ) ;
for ( int i = 0 ; i < 7 ; i + + ) {
boolean day = prefs . getBoolean ( " schedule_day " + i , true ) ;
2023-03-12 09:15:38 +00:00
boolean weekend = CalendarHelper . isWeekend ( context , i + 1 ) ;
size + = write ( os , String . format ( " schedule %s=%b %s \ r \ n " ,
daynames [ i + 1 ] , day , weekend ? " weekend " : " " ) ) ;
2022-01-31 14:08:59 +00:00
}
2020-08-30 11:35:21 +00:00
size + = write ( os , " \ r \ n " ) ;
}
2023-03-05 07:42:25 +00:00
for ( EntityAccount account : accounts )
if ( account . synchronize )
try {
2023-03-19 08:19:54 +00:00
String info = " pwd " ;
2023-03-05 07:42:25 +00:00
if ( account . auth_type = = ServiceAuthenticator . AUTH_TYPE_OAUTH | |
account . auth_type = = ServiceAuthenticator . AUTH_TYPE_GRAPH )
info = getTokenInfo ( account . password , account . auth_type ) ;
size + = write ( os , String . format ( " %s %s \ r \ n " , account . name , info ) ) ;
List < EntityIdentity > identities = db . identity ( ) . getSynchronizingIdentities ( account . id ) ;
for ( EntityIdentity identity : identities )
if ( identity . auth_type = = ServiceAuthenticator . AUTH_TYPE_OAUTH | |
identity . auth_type = = ServiceAuthenticator . AUTH_TYPE_GRAPH )
size + = write ( os , String . format ( " - %s %s \ r \ n " ,
identity . name , getTokenInfo ( identity . password , identity . auth_type ) ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , ex . toString ( ) + " \ r \ n " ) ;
}
size + = write ( os , " \ r \ n " ) ;
2023-03-04 14:26:46 +00:00
Map < Long , EntityFolder > unified = new HashMap < > ( ) ;
for ( EntityFolder folder : db . folder ( ) . getFoldersByType ( EntityFolder . INBOX ) )
unified . put ( folder . id , folder ) ;
for ( EntityFolder folder : db . folder ( ) . getFoldersUnified ( null , false ) )
unified . put ( folder . id , folder ) ;
for ( Long fid : unified . keySet ( ) ) {
EntityFolder folder = unified . get ( fid ) ;
EntityAccount account = db . account ( ) . getAccount ( folder . account ) ;
size + = write ( os , String . format ( " %s/%s:%s sync=%b unified=%b \ r \ n " ,
( account = = null ? null : account . name ) ,
folder . name , folder . type , folder . synchronize , folder . unified ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2022-01-31 14:08:59 +00:00
for ( EntityAccount account : accounts ) {
if ( account . synchronize ) {
int content = 0 ;
int messages = 0 ;
List < TupleFolderEx > folders = db . folder ( ) . getFoldersEx ( account . id ) ;
for ( TupleFolderEx folder : folders ) {
content + = folder . content ;
messages + = folder . messages ;
}
2021-08-07 07:42:52 +00:00
2023-09-02 09:39:14 +00:00
int blocked = db . contact ( ) . countBlocked ( account . id ) ;
2022-04-22 14:30:48 +00:00
boolean unmetered = false ;
2022-04-23 12:09:58 +00:00
boolean ignore_schedule = false ;
2022-04-22 14:30:48 +00:00
try {
if ( account . conditions ! = null ) {
JSONObject jconditions = new JSONObject ( account . conditions ) ;
unmetered = jconditions . optBoolean ( " unmetered " ) ;
2022-04-23 12:09:58 +00:00
ignore_schedule = jconditions . optBoolean ( " ignore_schedule " ) ;
2022-04-22 14:30:48 +00:00
}
} catch ( Throwable ignored ) {
}
2023-08-13 15:25:14 +00:00
size + = write ( os , account . id + " : " + account . name + ( account . primary ? " * " : " " ) +
2023-03-04 12:30:47 +00:00
" " + ( account . protocol = = EntityAccount . TYPE_IMAP ? " IMAP " : " POP " ) +
" [ " + ( account . provider = = null ? " " : account . provider ) +
" : " + ServiceAuthenticator . getAuthTypeName ( account . auth_type ) + " ] " +
2023-04-30 07:11:35 +00:00
" " + account . host + " : " + account . port + " / " +
EmailService . getEncryptionName ( account . encryption ) +
( account . insecure ? " !!! " : " " ) +
2022-01-31 14:08:59 +00:00
" sync= " + account . synchronize +
2023-07-21 19:05:47 +00:00
" exempted= " + account . poll_exempted + ( pollInterval > 0 & & account . poll_exempted ? " !!! " : " " ) +
2022-01-31 14:08:59 +00:00
" poll= " + account . poll_interval +
2023-04-16 09:56:16 +00:00
" ondemand= " + account . ondemand + ( account . ondemand ? " !!! " : " " ) +
2023-02-24 15:53:38 +00:00
" msgs= " + content + " / " + messages + " max= " + account . max_messages +
2023-09-02 09:39:14 +00:00
" blocked= " + blocked + ( blocked = = 0 ? " " : " !!! " ) +
2022-02-11 09:54:59 +00:00
" ops= " + db . operation ( ) . getOperationCount ( account . id ) +
2022-07-29 14:38:41 +00:00
" schedule= " + ( ! ignore_schedule ) + ( ignore_schedule ? " !!! " : " " ) +
2022-04-22 14:30:48 +00:00
" unmetered= " + unmetered + ( unmetered ? " !!! " : " " ) +
2023-07-12 20:41:16 +00:00
" quota= " + ( account . quota_usage = = null ? " - " : Helper . humanReadableByteCount ( account . quota_usage ) ) +
" / " + ( account . quota_limit = = null ? " - " : Helper . humanReadableByteCount ( account . quota_limit ) ) +
2022-01-31 14:08:59 +00:00
" " + account . state +
( account . last_connected = = null ? " " : " " + dtf . format ( account . last_connected ) ) +
2022-02-14 07:37:24 +00:00
( account . error = = null ? " " : " \ r \ n " + account . error ) +
2022-01-31 14:08:59 +00:00
" \ r \ n " ) ;
2021-08-07 07:42:52 +00:00
2022-01-31 14:08:59 +00:00
if ( folders . size ( ) > 0 )
Collections . sort ( folders , folders . get ( 0 ) . getComparator ( context ) ) ;
for ( TupleFolderEx folder : folders )
2023-04-30 07:11:35 +00:00
if ( folder . synchronize | | account . protocol = = EntityAccount . TYPE_POP ) {
2022-01-31 14:08:59 +00:00
int unseen = db . message ( ) . countUnseen ( folder . id ) ;
2023-02-24 16:12:13 +00:00
int hidden = db . message ( ) . countHidden ( folder . id ) ;
2022-01-31 14:08:59 +00:00
int notifying = db . message ( ) . countNotifying ( folder . id ) ;
2023-08-13 15:25:14 +00:00
size + = write ( os , " - " + folder . id + " : " + folder . name + " " +
2022-08-07 13:27:17 +00:00
folder . type + ( folder . inherited_type = = null ? " " : " / " + folder . inherited_type ) +
2022-01-31 14:08:59 +00:00
( folder . unified ? " unified " : " " ) +
( folder . notify ? " notify " : " " ) +
2023-08-05 06:55:50 +00:00
( Boolean . TRUE . equals ( folder . subscribed ) ? " subscribed " : " " ) +
2023-07-04 13:10:59 +00:00
" poll= " + folder . poll + ( folder . poll | | EntityFolder . INBOX . equals ( folder . type ) ? " " : " !!! " ) +
" factor= " + folder . poll_factor +
2023-04-30 07:11:35 +00:00
" days= " + getDays ( folder . sync_days ) + " / " + getDays ( folder . keep_days ) +
2022-01-31 14:08:59 +00:00
" msgs= " + folder . content + " / " + folder . messages + " / " + folder . total +
2022-02-11 09:54:59 +00:00
" ops= " + db . operation ( ) . getOperationCount ( folder . id , null ) +
2023-02-24 16:12:13 +00:00
" unseen= " + unseen + " hidden= " + hidden + " notifying= " + notifying +
2022-01-31 14:08:59 +00:00
" " + folder . state +
( folder . last_sync = = null ? " " : " " + dtf . format ( folder . last_sync ) ) +
" \ r \ n " ) ;
}
2021-08-07 07:42:52 +00:00
2022-03-28 06:32:50 +00:00
List < TupleAccountSwipes > swipes = db . account ( ) . getAccountSwipes ( account . id ) ;
if ( swipes = = null )
size + = write ( os , " <> swipes? \ r \ n " ) ;
else
for ( TupleAccountSwipes swipe : swipes ) {
size + = write ( os , " > " + EntityMessage . getSwipeType ( swipe . swipe_left ) + " " +
swipe . left_name + " : " + swipe . left_type + " \ r \ n " ) ;
size + = write ( os , " < " + EntityMessage . getSwipeType ( swipe . swipe_right ) + " " +
swipe . right_name + " : " + swipe . right_type + " \ r \ n " ) ;
}
2022-01-31 14:08:59 +00:00
size + = write ( os , " \ r \ n " ) ;
}
}
2021-08-07 07:42:52 +00:00
2022-02-14 07:37:24 +00:00
for ( EntityAccount account : accounts )
if ( account . synchronize ) {
List < EntityIdentity > identities = db . identity ( ) . getIdentities ( account . id ) ;
for ( EntityIdentity identity : identities )
if ( identity . synchronize ) {
size + = write ( os , account . name + " / " + identity . name + ( identity . primary ? " * " : " " ) + " " +
2023-02-02 06:53:59 +00:00
identity . display + " " + identity . email +
2023-01-28 09:14:46 +00:00
( identity . self ? " " : " !self " ) +
2023-03-04 12:30:47 +00:00
" [ " + ( identity . provider = = null ? " " : identity . provider ) +
" : " + ServiceAuthenticator . getAuthTypeName ( identity . auth_type ) + " ] " +
2023-01-28 09:14:46 +00:00
( TextUtils . isEmpty ( identity . sender_extra_regex ) ? " " : " regex= " + identity . sender_extra_regex ) +
( ! identity . sender_extra ? " " : " edit " +
( identity . sender_extra_name ? " +name " : " -name " ) +
( identity . reply_extra_name ? " +copy " : " -copy " ) ) +
2023-04-30 07:11:35 +00:00
" " + identity . host + " : " + identity . port + " / " +
EmailService . getEncryptionName ( identity . encryption ) +
( identity . insecure ? " !!! " : " " ) +
2022-02-14 07:37:24 +00:00
" ops= " + db . operation ( ) . getOperationCount ( EntityOperation . SEND ) +
2023-07-12 20:41:16 +00:00
" max= " + ( identity . max_size = = null ? " - " : Helper . humanReadableByteCount ( identity . max_size ) ) +
2022-02-14 07:37:24 +00:00
" " + identity . state +
( identity . last_connected = = null ? " " : " " + dtf . format ( identity . last_connected ) ) +
( identity . error = = null ? " " : " \ r \ n " + identity . error ) +
" \ r \ n " ) ;
}
}
size + = write ( os , " \ r \ n " ) ;
2022-02-11 09:54:59 +00:00
for ( EntityAccount account : accounts ) {
int ops = db . operation ( ) . getOperationCount ( account . id ) ;
if ( account . synchronize | | ops > 0 )
2022-01-31 14:08:59 +00:00
try {
JSONObject jaccount = account . toJSON ( ) ;
jaccount . put ( " state " , account . state = = null ? " null " : account . state ) ;
jaccount . put ( " warning " , account . warning ) ;
2022-02-11 09:54:59 +00:00
jaccount . put ( " operations " , ops ) ;
2022-01-31 14:08:59 +00:00
jaccount . put ( " error " , account . error ) ;
jaccount . put ( " capabilities " , account . capabilities ) ;
if ( account . last_connected ! = null )
jaccount . put ( " last_connected " , new Date ( account . last_connected ) . toString ( ) ) ;
jaccount . put ( " keep_alive_ok " , account . keep_alive_ok ) ;
jaccount . put ( " keep_alive_failed " , account . keep_alive_failed ) ;
jaccount . put ( " keep_alive_succeeded " , account . keep_alive_succeeded ) ;
jaccount . remove ( " password " ) ;
size + = write ( os , " ========== \ r \ n " ) ;
size + = write ( os , jaccount . toString ( 2 ) + " \ r \ n " ) ;
List < EntityFolder > folders = db . folder ( ) . getFolders ( account . id , false , false ) ;
if ( folders . size ( ) > 0 )
Collections . sort ( folders , folders . get ( 0 ) . getComparator ( context ) ) ;
for ( EntityFolder folder : folders ) {
JSONObject jfolder = folder . toJSON ( ) ;
2022-08-07 13:27:17 +00:00
jfolder . put ( " inherited_type " , folder . inherited_type ) ;
2022-01-31 14:08:59 +00:00
jfolder . put ( " level " , folder . level ) ;
jfolder . put ( " total " , folder . total ) ;
jfolder . put ( " initialize " , folder . initialize ) ;
jfolder . put ( " subscribed " , folder . subscribed ) ;
jfolder . put ( " state " , folder . state = = null ? " null " : folder . state ) ;
jfolder . put ( " sync_state " , folder . sync_state = = null ? " null " : folder . sync_state ) ;
jfolder . put ( " poll_count " , folder . poll_count ) ;
jfolder . put ( " read_only " , folder . read_only ) ;
jfolder . put ( " selectable " , folder . selectable ) ;
jfolder . put ( " inferiors " , folder . inferiors ) ;
jfolder . put ( " auto_add " , folder . auto_add ) ;
2023-04-18 15:59:28 +00:00
jfolder . put ( " flags " , folder . flags = = null ? null : TextUtils . join ( " , " , folder . flags ) ) ;
jfolder . put ( " keywords " , folder . keywords = = null ? null : TextUtils . join ( " , " , folder . keywords ) ) ;
2023-02-17 07:18:44 +00:00
jfolder . put ( " tbc " , Boolean . TRUE . equals ( folder . tbc ) ) ;
jfolder . put ( " rename " , folder . rename ) ;
jfolder . put ( " tbd " , Boolean . TRUE . equals ( folder . tbd ) ) ;
2022-02-11 09:54:59 +00:00
jfolder . put ( " operations " , db . operation ( ) . getOperationCount ( folder . id , null ) ) ;
2022-01-31 14:08:59 +00:00
jfolder . put ( " error " , folder . error ) ;
if ( folder . last_sync ! = null )
jfolder . put ( " last_sync " , new Date ( folder . last_sync ) . toString ( ) ) ;
if ( folder . last_sync_count ! = null )
jfolder . put ( " last_sync_count " , folder . last_sync_count ) ;
size + = write ( os , jfolder . toString ( 2 ) + " \ r \ n " ) ;
}
2021-08-07 07:42:52 +00:00
2022-01-31 14:08:59 +00:00
List < EntityIdentity > identities = db . identity ( ) . getIdentities ( account . id ) ;
for ( EntityIdentity identity : identities )
try {
JSONObject jidentity = identity . toJSON ( ) ;
jidentity . remove ( " password " ) ;
jidentity . remove ( " signature " ) ;
size + = write ( os , " ---------- \ r \ n " ) ;
size + = write ( os , jidentity . toString ( 2 ) + " \ r \ n " ) ;
} catch ( JSONException ex ) {
size + = write ( os , ex . toString ( ) + " \ r \ n " ) ;
}
} catch ( JSONException ex ) {
size + = write ( os , ex . toString ( ) + " \ r \ n " ) ;
2021-08-07 07:42:52 +00:00
}
2022-02-11 09:54:59 +00:00
}
2022-01-31 14:08:59 +00:00
}
2019-05-12 17:14:34 +00:00
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
2019-05-12 17:14:34 +00:00
}
}
2023-04-30 07:11:35 +00:00
private static String getDays ( Integer days ) {
if ( days = = null )
return " ? " ;
else
return ( days = = Integer . MAX_VALUE ? " ∞ " : Integer . toString ( days ) ) ;
}
2022-01-31 14:08:59 +00:00
private static void attachNetworkInfo ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " network.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2019-05-12 17:14:34 +00:00
2023-09-15 07:20:32 +00:00
Boolean isValidated = null ;
Boolean isCaptive = null ;
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
2022-04-13 20:27:33 +00:00
ConnectivityManager cm = Helper . getSystemService ( context , ConnectivityManager . class ) ;
2019-10-22 06:55:27 +00:00
2022-01-31 14:08:59 +00:00
NetworkInfo ani = cm . getActiveNetworkInfo ( ) ;
if ( ani ! = null )
2023-06-02 06:49:45 +00:00
size + = write ( os , " Active network info= " + ani +
" connecting= " + ani . isConnectedOrConnecting ( ) +
2022-01-31 14:08:59 +00:00
" connected= " + ani . isConnected ( ) +
2023-06-02 06:49:45 +00:00
" available= " + ani . isAvailable ( ) +
" state= " + ani . getState ( ) + " / " + ani . getDetailedState ( ) +
2022-01-31 14:08:59 +00:00
" metered= " + cm . isActiveNetworkMetered ( ) +
" roaming= " + ani . isRoaming ( ) +
" type= " + ani . getType ( ) + " / " + ani . getTypeName ( ) +
" \ r \ n \ r \ n " ) ;
2020-10-27 14:35:28 +00:00
2022-01-31 14:08:59 +00:00
Network active = ConnectionHelper . getActiveNetwork ( context ) ;
2023-06-02 06:49:45 +00:00
NetworkInfo a = ( active = = null ? null : cm . getNetworkInfo ( active ) ) ;
NetworkCapabilities c = ( active = = null ? null : cm . getNetworkCapabilities ( active ) ) ;
LinkProperties p = ( active = = null ? null : cm . getLinkProperties ( active ) ) ;
boolean n = ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) ;
size + = write ( os , " Active network= " + active + " native= " + n + " \ r \ n " ) ;
size + = write ( os , " info= " + a +
" connecting= " + ( a = = null ? null : a . isConnectedOrConnecting ( ) ) +
" connected= " + ( a = = null ? null : a . isConnected ( ) ) +
" available= " + ( a = = null ? null : a . isAvailable ( ) ) +
" state= " + ( a = = null ? null : a . getState ( ) + " / " + a . getDetailedState ( ) ) +
" roaming= " + ( a = = null ? null : a . isRoaming ( ) ) +
" type= " + ( a = = null ? null : a . getType ( ) + " / " + a . getTypeName ( ) ) +
" \ r \ n " ) ;
size + = write ( os , " caps= " + c + " \ r \ n " ) ;
size + = write ( os , " props= " + p + " \ r \ n \ r \ n " ) ;
2022-01-31 14:08:59 +00:00
for ( Network network : cm . getAllNetworks ( ) ) {
size + = write ( os , ( network . equals ( active ) ? " active= " : " network= " ) + network + " \ r \ n " ) ;
2020-10-27 14:35:28 +00:00
2022-01-31 14:08:59 +00:00
NetworkCapabilities caps = cm . getNetworkCapabilities ( network ) ;
size + = write ( os , " caps= " + caps + " \ r \ n " ) ;
2020-10-27 14:35:28 +00:00
2023-09-15 07:20:32 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
if ( isValidated = = null )
isValidated = false ;
if ( caps ! = null & & caps . hasCapability ( NetworkCapabilities . NET_CAPABILITY_VALIDATED ) )
isValidated = true ;
if ( isCaptive = = null )
isCaptive = false ;
if ( caps ! = null & & caps . hasCapability ( NetworkCapabilities . NET_CAPABILITY_CAPTIVE_PORTAL ) )
isCaptive = true ;
}
2022-01-31 14:08:59 +00:00
LinkProperties props = cm . getLinkProperties ( network ) ;
size + = write ( os , " props= " + props + " \ r \ n " ) ;
2020-02-12 11:56:19 +00:00
2021-06-20 18:40:08 +00:00
size + = write ( os , " \ r \ n " ) ;
}
2022-01-14 19:04:48 +00:00
2022-01-31 14:08:59 +00:00
try {
Enumeration < NetworkInterface > interfaces = NetworkInterface . getNetworkInterfaces ( ) ;
while ( interfaces ! = null & & interfaces . hasMoreElements ( ) ) {
NetworkInterface ni = interfaces . nextElement ( ) ;
size + = write ( os , " Interface= " + ni + " \ r \ n " ) ;
for ( InterfaceAddress iaddr : ni . getInterfaceAddresses ( ) ) {
InetAddress addr = iaddr . getAddress ( ) ;
size + = write ( os , " addr= " + addr +
( addr . isLoopbackAddress ( ) ? " loopback " : " " ) +
( addr . isSiteLocalAddress ( ) ? " site local (LAN) " : " " ) +
( addr . isLinkLocalAddress ( ) ? " link local (device) " : " " ) +
( addr . isAnyLocalAddress ( ) ? " any local " : " " ) +
( addr . isMulticastAddress ( ) ? " multicast " : " " ) + " \ r \ n " ) ;
}
size + = write ( os , " \ r \ n " ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , ex . getMessage ( ) + " \ r \ n " ) ;
}
2019-09-28 16:36:07 +00:00
2022-01-31 14:08:59 +00:00
ConnectionHelper . NetworkState state = ConnectionHelper . getNetworkState ( context ) ;
size + = write ( os , " Connected= " + state . isConnected ( ) + " \ r \ n " ) ;
size + = write ( os , " Suitable= " + state . isSuitable ( ) + " \ r \ n " ) ;
size + = write ( os , " Unmetered= " + state . isUnmetered ( ) + " \ r \ n " ) ;
2023-03-31 09:45:49 +00:00
size + = write ( os , " Roaming= " + state . isRoaming ( ) + " \ r \ n " ) ;
size + = write ( os , " \ r \ n " ) ;
2019-05-12 17:14:34 +00:00
2023-05-15 06:18:45 +00:00
boolean [ ] has46 = ConnectionHelper . has46 ( context ) ;
size + = write ( os , " Has IPv4= " + has46 [ 0 ] + " IPv6= " + has46 [ 1 ] + " \ r \ n " ) ;
2022-01-31 14:08:59 +00:00
size + = write ( os , " VPN active= " + ConnectionHelper . vpnActive ( context ) + " \ r \ n " ) ;
size + = write ( os , " Data saving= " + ConnectionHelper . isDataSaving ( context ) + " \ r \ n " ) ;
size + = write ( os , " Airplane= " + ConnectionHelper . airplaneMode ( context ) + " \ r \ n " ) ;
2023-03-31 09:45:49 +00:00
size + = write ( os , " \ r \ n " ) ;
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
2023-05-03 11:20:17 +00:00
int timeout = prefs . getInt ( " timeout " , EmailService . DEFAULT_CONNECT_TIMEOUT ) ;
2023-03-31 09:45:49 +00:00
boolean metered = prefs . getBoolean ( " metered " , true ) ;
boolean roaming = prefs . getBoolean ( " roaming " , true ) ;
boolean rlah = prefs . getBoolean ( " rlah " , true ) ;
boolean standalone_vpn = prefs . getBoolean ( " standalone_vpn " , false ) ;
boolean require_validated = prefs . getBoolean ( " require_validated " , false ) ;
boolean require_validated_captive = prefs . getBoolean ( " require_validated_captive " , true ) ;
boolean vpn_only = prefs . getBoolean ( " vpn_only " , false ) ;
2023-11-07 21:00:15 +00:00
boolean tcp_keep_alive = prefs . getBoolean ( " tcp_keep_alive " , false ) ;
boolean ssl_harden = prefs . getBoolean ( " ssl_harden " , false ) ;
boolean ssl_harden_strict = ( ssl_harden & & prefs . getBoolean ( " ssl_harden_strict " , false ) ) ;
boolean cert_strict = prefs . getBoolean ( " cert_strict " , ! BuildConfig . PLAY_STORE_RELEASE ) ;
boolean open_safe = prefs . getBoolean ( " open_safe " , false ) ;
2023-03-31 09:45:49 +00:00
2023-05-03 11:20:17 +00:00
size + = write ( os , " timeout= " + timeout + " s " + ( timeout = = EmailService . DEFAULT_CONNECT_TIMEOUT ? " " : " !!! " ) + " \ r \ n " ) ;
2023-03-31 09:45:49 +00:00
size + = write ( os , " metered= " + metered + ( metered ? " " : " !!! " ) + " \ r \ n " ) ;
size + = write ( os , " roaming= " + roaming + ( roaming ? " " : " !!! " ) + " \ r \ n " ) ;
size + = write ( os , " rlah= " + rlah + ( rlah ? " " : " !!! " ) + " \ r \ n " ) ;
2023-09-15 07:20:32 +00:00
size + = write ( os , " captive= " + ( isCaptive = = null ? " - " : Boolean . toString ( isCaptive ) ) + " \ r \ n " ) ;
size + = write ( os , " validation= " + require_validated + ( require_validated ? " !!! " : " " ) +
" captive= " + require_validated_captive + ( require_validated_captive ? " " : " !!! " ) + " \ r \ n " ) ;
size + = write ( os , " validated= " + ( isValidated = = null ? " - " : Boolean . toString ( isValidated ) ) +
( Boolean . FALSE . equals ( isValidated ) & &
( Boolean . TRUE . equals ( isCaptive ) ? require_validated_captive : require_validated ) ? " !!! " : " " ) + " \ r \ n " ) ;
2023-03-31 09:45:49 +00:00
size + = write ( os , " standalone_vpn= " + standalone_vpn + ( standalone_vpn ? " !!! " : " " ) + " \ r \ n " ) ;
size + = write ( os , " vpn_only= " + vpn_only + ( vpn_only ? " !!! " : " " ) + " \ r \ n " ) ;
2022-02-22 18:19:26 +00:00
2023-11-07 21:00:15 +00:00
size + = write ( os , " tcp_keep_alive= " + tcp_keep_alive + ( tcp_keep_alive ? " !!! " : " " ) + " \ r \ n " ) ;
size + = write ( os , " ssl_harden= " + ssl_harden + ( ssl_harden ? " !!! " : " " ) + " \ r \ n " ) ;
size + = write ( os , " ssl_harden_strict= " + ssl_harden_strict + ( ssl_harden_strict ? " !!! " : " " ) + " \ r \ n " ) ;
size + = write ( os , " cert_strict= " + cert_strict + ( cert_strict ? " !!! " : " " ) + " \ r \ n " ) ;
size + = write ( os , " open_safe= " + open_safe + " \ r \ n " ) ;
2022-02-22 18:19:26 +00:00
size + = write ( os , " \ r \ n " ) ;
size + = write ( os , getCiphers ( ) . toString ( ) ) ;
2023-11-11 10:39:53 +00:00
try {
String algo = TrustManagerFactory . getDefaultAlgorithm ( ) ;
TrustManagerFactory tmf = TrustManagerFactory . getInstance ( algo ) ;
tmf . init ( ( KeyStore ) null ) ;
TrustManager [ ] tms = tmf . getTrustManagers ( ) ;
if ( tms ! = null )
for ( TrustManager tm : tms ) {
size + = write ( os , String . format ( " Trust manager: %s (%s) \ n " ,
tm . getClass ( ) . getName ( ) , algo ) ) ;
if ( tm instanceof X509TrustManager )
for ( X509Certificate cert : ( ( X509TrustManager ) tm ) . getAcceptedIssuers ( ) )
size + = write ( os , String . format ( " - %s \ n " , cert . getIssuerDN ( ) ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , ex . getMessage ( ) + " \ r \ n " ) ;
}
2022-01-31 14:08:59 +00:00
}
2019-05-12 17:14:34 +00:00
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
2019-05-12 17:14:34 +00:00
}
}
2022-01-31 14:08:59 +00:00
private static void attachLog ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " log.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2019-05-12 17:14:34 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
long from = new Date ( ) . getTime ( ) - 24 * 3600 * 1000L ;
DateFormat TF = Helper . getTimeInstance ( context ) ;
2023-07-07 08:53:37 +00:00
for ( EntityLog entry : db . log ( ) . getLogs ( from , null ) )
if ( entry . data ! = null & & entry . data . contains ( " backoff= " ) )
size + = write ( os , String . format ( " %s %s \ r \ n " ,
TF . format ( entry . time ) ,
entry . data ) ) ;
size + = write ( os , " \ r \ n " ) ;
2022-06-14 05:51:57 +00:00
for ( EntityLog entry : db . log ( ) . getLogs ( from , null ) ) {
2023-03-21 16:35:30 +00:00
size + = write ( os , String . format ( " %s [%d:%d:%d:%d:%d] %s \ r \ n " ,
2022-01-31 14:08:59 +00:00
TF . format ( entry . time ) ,
entry . type . ordinal ( ) ,
2023-03-21 16:35:30 +00:00
( entry . thread = = null ? 0 : entry . thread ) ,
2022-01-31 14:08:59 +00:00
( entry . account = = null ? 0 : entry . account ) ,
( entry . folder = = null ? 0 : entry . folder ) ,
( entry . message = = null ? 0 : entry . message ) ,
entry . data ) ) ;
2022-06-14 05:51:57 +00:00
if ( size > MAX_LOG_SIZE ) {
size + = write ( os , " <truncated> \ r \ n " ) ;
break ;
}
}
2020-10-23 13:56:15 +00:00
}
2021-06-18 06:37:11 +00:00
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
2023-01-01 09:25:36 +00:00
if ( ! BuildConfig . DEBUG & & size > MIN_ZIP_SIZE )
2022-11-08 12:45:10 +00:00
attachment . zip ( context ) ;
2022-01-31 14:08:59 +00:00
} catch ( Throwable ex ) {
Log . e ( ex ) ;
2021-06-18 06:37:11 +00:00
}
}
2022-01-31 14:08:59 +00:00
private static void attachOperations ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " operations.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2019-05-12 17:14:34 +00:00
long size = 0 ;
2022-01-31 14:08:59 +00:00
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
DateFormat TF = Helper . getTimeInstance ( context ) ;
for ( EntityOperation op : db . operation ( ) . getOperations ( ) ) {
EntityAccount account = ( op . account = = null ? null : db . account ( ) . getAccount ( op . account ) ) ;
EntityFolder folder = ( op . folder = = null ? null : db . folder ( ) . getFolder ( op . folder ) ) ;
size + = write ( os , String . format ( " %s %s/%s %d %s/%d %s %s %s \ r \ n " ,
TF . format ( op . created ) ,
account = = null ? null : account . name ,
folder = = null ? null : folder . name ,
op . message = = null ? - 1 : op . message ,
op . name ,
op . tries ,
op . args ,
op . state ,
op . error ) ) ;
}
2019-05-12 17:14:34 +00:00
}
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
2022-01-31 14:08:59 +00:00
} catch ( Throwable ex ) {
Log . e ( ex ) ;
2019-05-12 17:14:34 +00:00
}
}
2022-01-31 14:08:59 +00:00
private static void attachTasks ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " tasks.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2020-10-09 12:29:30 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
for ( SimpleTask task : SimpleTask . getList ( ) )
size + = write ( os , String . format ( " %s \ r \ n " , task . toString ( ) ) ) ;
size + = write ( os , " \ r \ n " ) ;
for ( TwoStateOwner owner : TwoStateOwner . getList ( ) )
size + = write ( os , String . format ( " %s \ r \ n " , owner . toString ( ) ) ) ;
2021-09-27 14:32:21 +00:00
}
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
}
2021-09-27 14:32:21 +00:00
2022-01-31 14:08:59 +00:00
private static void attachLogcat ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " logcat.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
Process proc = null ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
String [ ] cmd = new String [ ] { " logcat " ,
" -d " ,
" -v " , " threadtime " ,
//"-t", "1000",
Log . TAG + " :I " } ;
proc = Runtime . getRuntime ( ) . exec ( cmd ) ;
long size = 0 ;
try ( BufferedReader br = new BufferedReader ( new InputStreamReader ( proc . getInputStream ( ) ) ) ) {
String line ;
while ( ( line = br . readLine ( ) ) ! = null )
size + = write ( os , line + " \ r \ n " ) ;
2020-10-09 12:29:30 +00:00
}
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
2023-01-01 09:25:36 +00:00
if ( ! BuildConfig . DEBUG & & size > MIN_ZIP_SIZE )
2022-11-08 12:45:10 +00:00
attachment . zip ( context ) ;
2022-01-31 14:08:59 +00:00
} finally {
if ( proc ! = null )
proc . destroy ( ) ;
}
} catch ( Throwable ex ) {
Log . e ( ex ) ;
2020-10-09 12:29:30 +00:00
}
}
2022-01-31 14:08:59 +00:00
@RequiresApi ( api = Build . VERSION_CODES . O )
private static void attachNotificationInfo ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
2022-03-08 19:59:21 +00:00
attachment . name = " notification.txt " ;
2022-01-31 14:08:59 +00:00
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2022-01-31 12:36:19 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
2022-04-13 20:27:33 +00:00
NotificationManager nm = Helper . getSystemService ( context , NotificationManager . class ) ;
2022-01-31 14:08:59 +00:00
2022-06-09 13:11:02 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . TIRAMISU ) {
2023-06-03 18:56:52 +00:00
boolean permission = Helper . hasPermission ( context , Manifest . permission . POST_NOTIFICATIONS ) ;
2022-06-09 13:11:02 +00:00
boolean enabled = nm . areNotificationsEnabled ( ) ;
2023-06-03 18:56:52 +00:00
size + = write ( os , String . format ( " Permission=%b %s Enabled=%b %s \ r \ n " ,
permission , ( permission ? " " : " !!! " ) ,
2022-06-09 13:11:02 +00:00
enabled , ( enabled ? " " : " !!! " ) ) ) ;
}
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . Q ) {
boolean paused = nm . areNotificationsPaused ( ) ;
size + = write ( os , String . format ( " Paused=%b %s \ r \ n " ,
paused , ( paused ? " !!! " : " " ) ) ) ;
}
2022-01-31 14:08:59 +00:00
int filter = nm . getCurrentInterruptionFilter ( ) ;
2022-03-08 19:59:21 +00:00
size + = write ( os , String . format ( " Interruption filter allow=%s %s \ r \ n \ r \ n " ,
2022-07-29 16:11:32 +00:00
Helper . getInterruptionFilter ( filter ) ,
( filter = = NotificationManager . INTERRUPTION_FILTER_ALL ? " " : " !!! " ) ) ) ;
2022-01-31 14:08:59 +00:00
2022-07-30 21:02:17 +00:00
size + = write ( os , String . format ( " InCall=%b DND=%b \ r \ n \ r \ n " ,
MediaPlayerHelper . isInCall ( context ) ,
MediaPlayerHelper . isDnd ( context ) ) ) ;
2023-06-25 05:46:48 +00:00
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
StringBuilder options = new StringBuilder ( ) ;
for ( String key : prefs . getAll ( ) . keySet ( ) )
if ( key . startsWith ( " notify_ " ) ) {
Object value = prefs . getAll ( ) . get ( key ) ;
boolean mark = false ;
if ( " notify_known " . equals ( key ) & & Boolean . TRUE . equals ( value ) )
mark = true ;
if ( " notify_background_only " . equals ( key ) & & Boolean . TRUE . equals ( value ) )
mark = true ;
if ( " notify_suppress_in_car " . equals ( key ) & & Boolean . TRUE . equals ( value ) )
mark = true ;
options . append ( ' ' ) . append ( key ) . append ( '=' )
. append ( value )
. append ( mark ? " !!! " : " " )
. append ( " \ r \ n " ) ;
}
if ( options . length ( ) > 0 ) {
options . append ( " \ r \ n " ) ;
size + = write ( os , options . toString ( ) ) ;
}
2022-01-31 14:08:59 +00:00
for ( NotificationChannel channel : nm . getNotificationChannels ( ) )
try {
JSONObject jchannel = NotificationHelper . channelToJSON ( channel ) ;
size + = write ( os , jchannel . toString ( 2 ) + " \ r \ n \ r \ n " ) ;
} catch ( JSONException ex ) {
2022-07-29 16:11:32 +00:00
size + = write ( os , ex + " \ r \ n " ) ;
2022-01-31 13:43:40 +00:00
}
2022-01-31 14:08:59 +00:00
size + = write ( os ,
String . format ( " Importance none=%d; min=%d; low=%d; default=%d; high=%d; max=%d; unspecified=%d \ r \ n " ,
NotificationManager . IMPORTANCE_NONE ,
NotificationManager . IMPORTANCE_MIN ,
NotificationManager . IMPORTANCE_LOW ,
NotificationManager . IMPORTANCE_DEFAULT ,
NotificationManager . IMPORTANCE_HIGH ,
NotificationManager . IMPORTANCE_MAX ,
NotificationManager . IMPORTANCE_UNSPECIFIED ) ) ;
size + = write ( os ,
String . format ( " Visibility private=%d; public=%d; secret=%d \ r \ n " ,
Notification . VISIBILITY_PRIVATE ,
Notification . VISIBILITY_PUBLIC ,
Notification . VISIBILITY_SECRET ) ) ;
2022-07-29 16:02:52 +00:00
size + = write ( os , String . format ( " Interruption filter \ r \ n " ) ) ;
size + = write ( os , String . format ( " - All: no notifications are suppressed. \ r \ n " ) ) ;
size + = write ( os , String . format ( " - Priority: all notifications are suppressed except those that match the priority criteria. Some audio streams are muted. \ r \ n " ) ) ;
size + = write ( os , String . format ( " - None: all notifications are suppressed and all audio streams (except those used for phone calls) and vibrations are muted. \ r \ n " ) ) ;
size + = write ( os , String . format ( " - Alarm: all notifications except those of category alarm are suppressed. Some audio streams are muted. \ r \ n " ) ) ;
2022-01-31 12:36:19 +00:00
}
2022-01-31 13:43:40 +00:00
2022-01-31 14:08:59 +00:00
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
}
2022-01-31 13:43:40 +00:00
2022-01-31 14:08:59 +00:00
private static void attachEnvironment ( Context context , long id , int sequence ) {
try {
DB db = DB . getInstance ( context ) ;
2022-01-31 13:43:40 +00:00
2022-01-31 14:08:59 +00:00
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " environment.txt " ;
attachment . type = " text/plain " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
2022-01-31 13:43:40 +00:00
2022-01-31 14:08:59 +00:00
long now = new Date ( ) . getTime ( ) ;
2023-04-02 08:28:54 +00:00
PackageManager pm = context . getPackageManager ( ) ;
2022-01-31 13:43:40 +00:00
2022-01-31 14:08:59 +00:00
long size = 0 ;
File file = attachment . getFile ( context ) ;
try ( OutputStream os = new BufferedOutputStream ( new FileOutputStream ( file ) ) ) {
2023-08-02 14:54:22 +00:00
size + = write ( os , String . format ( " Photo picker=%b \ r \ n " , Helper . hasPhotoPicker ( ) ) ) ;
size + = write ( os , String . format ( " Double tap timeout=%d \ r \ n " , ViewConfiguration . getDoubleTapTimeout ( ) ) ) ;
size + = write ( os , String . format ( " Long press timeout=%d \ r \ n " , ViewConfiguration . getLongPressTimeout ( ) ) ) ;
2023-06-14 18:48:40 +00:00
for ( Class < ? > cls : new Class [ ] {
ActivitySendSelf . class ,
ActivitySearch . class ,
ActivityAnswer . class ,
ReceiverAutoStart . class } )
size + = write ( os , String . format ( " %s=%b \ r \ n " ,
cls . getSimpleName ( ) , Helper . isComponentEnabled ( context , cls ) ) ) ;
size + = write ( os , " \ r \ n " ) ;
2023-06-15 18:33:06 +00:00
2023-11-11 06:59:22 +00:00
try {
ApplicationInfo app = pm . getApplicationInfo ( context . getPackageName ( ) , PackageManager . GET_META_DATA ) ;
List < String > metas = getExtras ( app . metaData ) ;
size + = write ( os , " Manifest metas= " + ( metas = = null ? null : metas . size ( ) ) + " \ r \ n " ) ;
for ( String meta : metas )
size + = write ( os , String . format ( " %s \ r \ n " , meta ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
int flags = PackageManager . GET_RESOLVED_FILTER ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M )
flags | = PackageManager . MATCH_ALL ;
2023-06-15 18:33:06 +00:00
try {
Intent home = new Intent ( Intent . ACTION_MAIN ) . addCategory ( Intent . CATEGORY_HOME ) ;
List < ResolveInfo > homes = context . getPackageManager ( ) . queryIntentActivities ( home , PackageManager . MATCH_DEFAULT_ONLY ) ;
2023-11-11 06:59:22 +00:00
size + = write ( os , " Launchers= " + ( homes = = null ? null : homes . size ( ) ) + " \ r \ n " ) ;
2023-06-15 18:33:06 +00:00
if ( homes ! = null )
for ( ResolveInfo ri : homes )
size + = write ( os , String . format ( " Launcher=%s \ r \ n " , ri . activityInfo . packageName ) ) ;
ResolveInfo rid = context . getPackageManager ( ) . resolveActivity ( home , PackageManager . MATCH_DEFAULT_ONLY ) ;
size + = write ( os , String . format ( " Default launcher=%s \ r \ n " , ( rid = = null ? null : rid . activityInfo . packageName ) ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2023-06-15 20:37:26 +00:00
size + = write ( os , " \ r \ n " ) ;
2023-06-15 18:33:06 +00:00
2023-10-31 09:00:16 +00:00
try {
2023-11-11 06:59:22 +00:00
Intent intent = new Intent ( Intent . ACTION_VIEW )
//.addCategory(Intent.CATEGORY_BROWSABLE)
. setData ( Uri . parse ( " http://example.com/ " ) ) ;
2023-11-08 09:59:55 +00:00
ResolveInfo main = pm . resolveActivity ( intent , 0 ) ;
2023-06-15 20:37:26 +00:00
List < ResolveInfo > ris = pm . queryIntentActivities ( intent , flags ) ;
size + = write ( os , " Browsers= " + ( ris = = null ? null : ris . size ( ) ) + " \ r \ n " ) ;
if ( ris ! = null )
for ( ResolveInfo ri : ris ) {
2023-11-11 06:59:22 +00:00
CharSequence label = pm . getApplicationLabel ( ri . activityInfo . applicationInfo ) ;
2023-06-15 20:37:26 +00:00
Intent serviceIntent = new Intent ( ) ;
2023-11-11 06:59:22 +00:00
serviceIntent . setAction ( ACTION_CUSTOM_TABS_CONNECTION ) ;
2023-06-15 20:37:26 +00:00
serviceIntent . setPackage ( ri . activityInfo . packageName ) ;
boolean tabs = ( pm . resolveService ( serviceIntent , 0 ) ! = null ) ;
StringBuilder sb = new StringBuilder ( ) ;
sb . append ( " Browser= " ) . append ( ri . activityInfo . packageName ) ;
2023-11-11 06:59:22 +00:00
if ( Objects . equals ( main = = null ? null : main . activityInfo . packageName , ri . activityInfo . packageName ) )
2023-11-08 09:59:55 +00:00
sb . append ( " * " ) ;
2023-11-11 06:59:22 +00:00
sb . append ( " ( " ) . append ( label ) . append ( " ) " ) ;
2023-06-15 20:37:26 +00:00
sb . append ( " tabs= " ) . append ( tabs ) ;
sb . append ( " view= " ) . append ( ri . filter . hasAction ( Intent . ACTION_VIEW ) ) ;
sb . append ( " browsable= " ) . append ( ri . filter . hasCategory ( Intent . CATEGORY_BROWSABLE ) ) ;
sb . append ( " authorities= " ) . append ( ri . filter . authoritiesIterator ( ) ! = null ) ;
sb . append ( " schemes= " ) ;
boolean first = true ;
Iterator < String > schemeIter = ri . filter . schemesIterator ( ) ;
while ( schemeIter . hasNext ( ) ) {
String scheme = schemeIter . next ( ) ;
if ( first )
first = false ;
else
sb . append ( ',' ) ;
sb . append ( scheme ) ;
}
if ( tabs & & BuildConfig . DEBUG )
try {
boolean bindable = context . bindService ( serviceIntent , new CustomTabsServiceConnection ( ) {
@Override
public void onCustomTabsServiceConnected ( @NonNull final ComponentName component , final CustomTabsClient client ) {
try {
context . unbindService ( this ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
}
@Override
public void onServiceDisconnected ( final ComponentName component ) {
// Do nothing
}
} , 0 ) ;
sb . append ( " bindable= " ) . append ( bindable ) ;
} catch ( Throwable ex ) {
size + = write ( os , ex . toString ( ) ) ;
}
sb . append ( " \ r \ n " ) ;
2023-11-11 06:59:22 +00:00
size + = write ( os , sb . toString ( ) ) ;
}
2023-06-15 20:37:26 +00:00
2023-11-11 06:59:22 +00:00
SharedPreferences prefs = PreferenceManager . getDefaultSharedPreferences ( context ) ;
String open_with_pkg = prefs . getString ( " open_with_pkg " , null ) ;
boolean open_with_tabs = prefs . getBoolean ( " open_with_tabs " , true ) ;
size + = write ( os , String . format ( " Selected: %s tabs=%b \ r \ n " ,
open_with_pkg , open_with_tabs ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
try {
Intent intent = new Intent ( MediaStore . Audio . Media . RECORD_SOUND_ACTION ) ;
ResolveInfo main = pm . resolveActivity ( intent , 0 ) ;
List < ResolveInfo > ris = pm . queryIntentActivities ( intent , flags ) ;
size + = write ( os , " Recorders= " + ( ris = = null ? null : ris . size ( ) ) + " \ r \ n " ) ;
if ( ris ! = null )
for ( ResolveInfo ri : ris ) {
CharSequence label = pm . getApplicationLabel ( ri . activityInfo . applicationInfo ) ;
StringBuilder sb = new StringBuilder ( ) ;
sb . append ( " Recorder= " ) . append ( ri . activityInfo . packageName ) ;
if ( Objects . equals ( main . activityInfo . packageName , ri . activityInfo . packageName ) )
sb . append ( " * " ) ;
sb . append ( " ( " ) . append ( label ) . append ( " ) " ) ;
sb . append ( " \ r \ n " ) ;
2023-06-15 20:37:26 +00:00
size + = write ( os , sb . toString ( ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2023-06-15 18:33:06 +00:00
size + = write ( os , " \ r \ n " ) ;
2023-06-14 18:48:40 +00:00
2023-01-18 07:44:45 +00:00
try {
List < UriPermission > uperms = context . getContentResolver ( ) . getPersistedUriPermissions ( ) ;
2023-11-11 06:59:22 +00:00
size + = write ( os , " Persisted URIs= " + ( uperms = = null ? null : uperms . size ( ) ) + " \ r \ n " ) ;
2023-01-18 07:44:45 +00:00
if ( uperms ! = null )
for ( UriPermission uperm : uperms ) {
size + = write ( os , String . format ( " %s r=%b w=%b %s \ r \ n " ,
uperm . getUri ( ) . toString ( ) ,
uperm . isReadPermission ( ) ,
uperm . isWritePermission ( ) ,
new Date ( uperm . getPersistedTime ( ) ) ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2022-01-31 13:43:40 +00:00
try {
2023-04-02 08:28:54 +00:00
PackageInfo pi = pm . getPackageInfo ( BuildConfig . APPLICATION_ID , PackageManager . GET_PERMISSIONS ) ;
2022-01-31 14:08:59 +00:00
for ( int i = 0 ; i < pi . requestedPermissions . length ; i + + )
if ( pi . requestedPermissions [ i ] ! = null & &
pi . requestedPermissions [ i ] . startsWith ( " android.permission. " ) ) {
boolean granted = ( ( pi . requestedPermissionsFlags [ i ] & PackageInfo . REQUESTED_PERMISSION_GRANTED ) ! = 0 ) ;
size + = write ( os , String . format ( " %s=%b \ r \ n " ,
pi . requestedPermissions [ i ] . replace ( " android.permission. " , " " ) , granted ) ) ;
}
2022-01-31 13:43:40 +00:00
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2022-09-09 06:21:15 +00:00
for ( String prop : NETWORK_PROPS )
size + = write ( os , prop + " = " + System . getProperty ( prop ) + " \ r \ n " ) ;
size + = write ( os , " \ r \ n " ) ;
2022-06-18 10:18:35 +00:00
ApplicationInfo ai = context . getApplicationInfo ( ) ;
if ( ai ! = null )
size + = write ( os , String . format ( " Source: %s \ r \ n public: %s \ r \ n " ,
ai . sourceDir , ai . publicSourceDir ) ) ;
2022-09-05 20:51:26 +00:00
size + = write ( os , String . format ( " Files: %s \ r \ n external: %s \ r \ n storage: %s \ r \ n " ,
2022-11-03 15:57:53 +00:00
context . getFilesDir ( ) , Helper . getExternalFilesDir ( context ) ,
2022-09-05 20:51:26 +00:00
Environment . getExternalStorageDirectory ( ) ) ) ;
2022-06-18 10:18:35 +00:00
size + = write ( os , String . format ( " Cache: %s \ r \ n external: %s \ n " ,
context . getCacheDir ( ) , context . getExternalCacheDir ( ) ) ) ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . N )
size + = write ( os , String . format ( " Data: %s \ r \ n " , context . getDataDir ( ) . getAbsolutePath ( ) ) ) ;
size + = write ( os , String . format ( " Database: %s \ r \ n " ,
context . getDatabasePath ( DB . DB_NAME ) ) ) ;
2022-09-29 05:19:39 +00:00
try ( Cursor cursor = SQLiteDatabase . create ( null ) . rawQuery (
" SELECT sqlite_version() AS sqlite_version " , null ) ) {
if ( cursor . moveToNext ( ) )
size + = write ( os , String . format ( " sqlite: %s \ r \ n " , cursor . getString ( 0 ) ) ) ;
}
2022-10-14 07:02:53 +00:00
try {
TupleFtsStats stats = db . message ( ) . getFts ( ) ;
size + = write ( os , String . format ( " fts: %d/%d %s \ r \ n " , stats . fts , stats . total ,
Helper . humanReadableByteCount ( Fts4DbHelper . size ( context ) ) ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2022-09-29 05:19:39 +00:00
2022-06-18 10:18:35 +00:00
size + = write ( os , " \ r \ n " ) ;
2023-03-03 07:55:29 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . S ) {
try {
DomainVerificationManager dvm = Helper . getSystemService ( context , DomainVerificationManager . class ) ;
DomainVerificationUserState userState = dvm . getDomainVerificationUserState ( context . getPackageName ( ) ) ;
Map < String , Integer > hostToStateMap = userState . getHostToStateMap ( ) ;
for ( String key : hostToStateMap . keySet ( ) ) {
Integer stateValue = hostToStateMap . get ( key ) ;
if ( stateValue = = DomainVerificationUserState . DOMAIN_STATE_VERIFIED )
size + = write ( os , String . format ( " Verified: %s \ r \ n " , key ) ) ;
else if ( stateValue = = DomainVerificationUserState . DOMAIN_STATE_SELECTED )
size + = write ( os , String . format ( " selected: %s \ r \ n " , key ) ) ;
else
size + = write ( os , String . format ( " Unverified: %s (%d) \ r \ n " , key ,
stateValue = = null ? - 1 : stateValue ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
}
2023-01-24 07:00:30 +00:00
try {
List < WorkInfo > works = WorkManager
. getInstance ( context )
. getWorkInfos ( WorkQuery . fromStates (
WorkInfo . State . ENQUEUED ,
WorkInfo . State . BLOCKED ,
WorkInfo . State . RUNNING ) )
. get ( ) ;
for ( WorkInfo work : works ) {
size + = write ( os , String . format ( " Work: %s \ r \ n " ,
work . toString ( ) ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2023-04-25 06:17:29 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . TIRAMISU )
try {
Map < Integer , Integer > exts = SdkExtensions . getAllExtensionVersions ( ) ;
for ( Integer ext : exts . keySet ( ) )
size + = write ( os , String . format ( " Extension %d / %d \ r \ n " , ext , exts . get ( ext ) ) ) ;
if ( exts . size ( ) > 0 )
size + = write ( os , " \ r \ n " ) ;
size + = write ( os , String . format ( " Max. pick images: %d \ r \ n \ r \ n " , MediaStore . getPickImagesMaxLimit ( ) ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2022-08-10 18:53:01 +00:00
2022-06-14 13:22:39 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . O ) {
try {
for ( FileStore store : FileSystems . getDefault ( ) . getFileStores ( ) )
if ( ! store . isReadOnly ( ) & &
store . getUsableSpace ( ) ! = 0 & &
! " tmpfs " . equals ( store . type ( ) ) ) {
long total = store . getTotalSpace ( ) ;
long unalloc = store . getUnallocatedSpace ( ) ;
size + = write ( os , String . format ( " %s %s %s/%s \ r \ n " ,
store ,
store . type ( ) ,
Helper . humanReadableByteCount ( total - unalloc ) ,
Helper . humanReadableByteCount ( total ) ) ) ;
}
} catch ( IOException ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
}
2022-12-27 14:22:39 +00:00
List < File > files = new ArrayList < > ( ) ;
try {
files . addAll ( Helper . listFiles ( context . getFilesDir ( ) , MIN_FILE_SIZE ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
try {
files . addAll ( Helper . listFiles ( context . getCacheDir ( ) , MIN_FILE_SIZE ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
Collections . sort ( files , new Comparator < File > ( ) {
@Override
public int compare ( File f1 , File f2 ) {
return - Long . compare ( f1 . length ( ) , f2 . length ( ) ) ;
}
} ) ;
for ( int i = 0 ; i < Math . min ( 100 , files . size ( ) ) ; i + + )
size + = write ( os , String . format ( " %d %s %s \ r \ n " , i + 1 ,
Helper . humanReadableByteCount ( files . get ( i ) . length ( ) ) ,
files . get ( i ) . getAbsoluteFile ( ) ) ) ;
size + = write ( os , " \ r \ n " ) ;
2022-01-31 14:08:59 +00:00
size + = write ( os , String . format ( " Configuration: %s \ r \ n \ r \ n " ,
context . getResources ( ) . getConfiguration ( ) ) ) ;
for ( Provider p : Security . getProviders ( ) )
size + = write ( os , String . format ( " %s \ r \ n " , p ) ) ;
size + = write ( os , " \ r \ n " ) ;
2023-11-11 14:46:40 +00:00
String pgpPackage = PgpHelper . getPackageName ( context ) ;
boolean pgpInstalled = PgpHelper . isOpenKeychainInstalled ( context ) ;
size + = write ( os , String . format ( " %s=%b \ r \ n " , pgpPackage , pgpInstalled ) ) ;
if ( pgpInstalled )
try {
PackageInfo pi = pm . getPackageInfo ( pgpPackage , PackageManager . GET_PERMISSIONS ) ;
for ( int i = 0 ; i < pi . requestedPermissions . length ; i + + ) {
boolean granted = ( ( pi . requestedPermissionsFlags [ i ] & PackageInfo . REQUESTED_PERMISSION_GRANTED ) ! = 0 ) ;
size + = write ( os , String . format ( " - %s=%b \ r \ n " , pi . requestedPermissions [ i ] , granted ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2022-01-31 14:08:59 +00:00
2022-01-31 13:43:40 +00:00
try {
2022-01-31 14:08:59 +00:00
int maxKeySize = javax . crypto . Cipher . getMaxAllowedKeyLength ( " AES " ) ;
size + = write ( os , context . getString ( R . string . title_advanced_aes_key_size ,
Helper . humanReadableByteCount ( maxKeySize , false ) ) ) ;
size + = write ( os , " \ r \ n " ) ;
2022-01-31 13:43:40 +00:00
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2022-01-31 14:08:59 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
try {
Map < String , String > stats = Debug . getRuntimeStats ( ) ;
for ( String key : stats . keySet ( ) )
size + = write ( os , String . format ( " %s=%s \ r \ n " , key , stats . get ( key ) ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
2022-01-31 13:43:40 +00:00
}
2022-01-31 14:08:59 +00:00
size + = write ( os , " \ r \ n " ) ;
}
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . R ) {
try {
// https://developer.android.com/reference/android/app/ApplicationExitInfo
2022-04-13 20:27:33 +00:00
ActivityManager am = Helper . getSystemService ( context , ActivityManager . class ) ;
2022-01-31 14:08:59 +00:00
List < ApplicationExitInfo > infos = am . getHistoricalProcessExitReasons (
2022-06-18 19:34:16 +00:00
context . getPackageName ( ) , 0 , 100 ) ;
2022-01-31 14:08:59 +00:00
for ( ApplicationExitInfo info : infos )
2022-06-18 19:34:16 +00:00
size + = write ( os , String . format ( " %s: %s %s/%s reason=%s status=%d importance=%d \ r \ n " ,
2022-01-31 14:08:59 +00:00
new Date ( info . getTimestamp ( ) ) , info . getDescription ( ) ,
Helper . humanReadableByteCount ( info . getPss ( ) * 1024L ) ,
Helper . humanReadableByteCount ( info . getRss ( ) * 1024L ) ,
2022-06-19 06:24:13 +00:00
Helper . getExitReason ( info . getReason ( ) ) , info . getStatus ( ) , info . getImportance ( ) ) ) ;
2022-01-31 14:08:59 +00:00
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
size + = write ( os , " \ r \ n " ) ;
2022-01-31 13:43:40 +00:00
}
2022-01-31 12:36:19 +00:00
2022-01-31 14:08:59 +00:00
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . P )
try {
2022-04-13 20:27:33 +00:00
UsageStatsManager usm = Helper . getSystemService ( context , UsageStatsManager . class ) ;
2022-01-31 14:08:59 +00:00
UsageEvents events = usm . queryEventsForSelf ( now - 12 * 3600L , now ) ;
UsageEvents . Event event = new UsageEvents . Event ( ) ;
while ( events ! = null & & events . hasNextEvent ( ) ) {
events . getNextEvent ( event ) ;
size + = write ( os , String . format ( " %s %s %s b=%d s=%d \ r \ n " ,
new Date ( event . getTimeStamp ( ) ) ,
2022-06-19 06:24:13 +00:00
Helper . getEventType ( event . getEventType ( ) ) ,
2022-01-31 14:08:59 +00:00
event . getClassName ( ) ,
event . getAppStandbyBucket ( ) ,
event . getShortcutId ( ) ) ) ;
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2022-03-07 12:18:08 +00:00
try {
List < PermissionGroupInfo > groups = pm . getAllPermissionGroups ( 0 ) ;
groups . add ( 0 , null ) ; // Ungrouped
for ( PermissionGroupInfo group : groups ) {
String name = ( group = = null ? null : group . name ) ;
size + = write ( os , String . format ( " \ r \ n%s \ r \ n " , name = = null ? " Ungrouped " : name ) ) ;
size + = write ( os , " ---------------------------------------- \ r \ n " ) ;
try {
for ( PermissionInfo permission : pm . queryPermissionsByGroup ( name , 0 ) )
size + = write ( os , String . format ( " %s \ r \ n " , permission . name ) ) ;
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
}
} catch ( Throwable ex ) {
size + = write ( os , String . format ( " %s \ r \ n " , ex ) ) ;
}
2022-01-31 14:08:59 +00:00
}
db . attachment ( ) . setDownloaded ( attachment . id , size ) ;
} catch ( Throwable ex ) {
Log . e ( ex ) ;
}
2022-01-31 12:36:19 +00:00
}
2021-01-03 09:58:51 +00:00
private static void attachClassifierData ( Context context , long id , int sequence ) throws IOException , JSONException {
DB db = DB . getInstance ( context ) ;
EntityAttachment attachment = new EntityAttachment ( ) ;
attachment . message = id ;
attachment . sequence = sequence ;
attachment . name = " classifier.json " ;
attachment . type = " application/json " ;
attachment . disposition = Part . ATTACHMENT ;
attachment . size = null ;
attachment . progress = 0 ;
attachment . id = db . attachment ( ) . insertAttachment ( attachment ) ;
MessageClassifier . save ( context ) ;
2022-03-13 13:31:41 +00:00
File source = MessageClassifier . getFile ( context , false ) ;
2021-01-03 09:58:51 +00:00
File target = attachment . getFile ( context ) ;
Helper . copy ( source , target ) ;
db . attachment ( ) . setDownloaded ( attachment . id , target . length ( ) ) ;
}
2023-03-05 07:42:25 +00:00
static String getTokenInfo ( String password , int auth_type ) throws JSONException {
AuthState authState = AuthState . jsonDeserialize ( password ) ;
Long expiration = authState . getAccessTokenExpirationTime ( ) ;
TokenResponse t = authState . getLastTokenResponse ( ) ;
Set < String > scopeSet = ( t = = null ? null : t . getScopeSet ( ) ) ;
String [ ] scopes = ( scopeSet = = null ? new String [ 0 ] : scopeSet . toArray ( new String [ 0 ] ) ) ;
return String . format ( " %s expire=%s need=%b %s " ,
ServiceAuthenticator . getAuthTypeName ( auth_type ) ,
( expiration = = null ? null : new Date ( expiration ) ) ,
authState . getNeedsTokenRefresh ( ) ,
TextUtils . join ( " , " , scopes ) ) ;
}
2022-02-22 18:19:26 +00:00
static SpannableStringBuilder getCiphers ( ) {
SpannableStringBuilder ssb = new SpannableStringBuilderEx ( ) ;
2023-11-10 07:30:22 +00:00
for ( Provider provider : new Provider [ ] {
null , // Android
new BouncyCastleJsseProvider ( ) ,
new BouncyCastleJsseProvider ( true ) } )
2023-11-09 20:17:52 +00:00
for ( String protocol : new String [ ] { " SSL " , " TLS " } )
try {
int begin = ssb . length ( ) ;
2023-11-10 07:30:22 +00:00
SSLContext sslContext = ( provider = = null
? SSLContext . getInstance ( protocol )
: SSLContext . getInstance ( protocol , provider ) ) ;
ssb . append ( " SSL protocol: " ) . append ( sslContext . getProtocol ( ) ) . append ( " \ r \ n " ) ;
Provider sslProvider = sslContext . getProvider ( ) ;
ssb . append ( " SSL provider: " ) . append ( sslProvider . getName ( ) ) ;
if ( sslProvider instanceof BouncyCastleJsseProvider ) {
boolean fips = ( ( BouncyCastleJsseProvider ) sslProvider ) . isFipsMode ( ) ;
if ( fips )
ssb . append ( " FIPS " ) ;
}
ssb . append ( " \ r \ n " ) ;
ssb . append ( " SSL class: " ) . append ( sslProvider . getClass ( ) . getName ( ) ) . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
ssb . setSpan ( new StyleSpan ( Typeface . BOLD ) , begin , ssb . length ( ) , 0 ) ;
2023-11-10 07:30:22 +00:00
ssb . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
TrustManagerFactory tmf = TrustManagerFactory . getInstance ( TrustManagerFactory . getDefaultAlgorithm ( ) ) ;
tmf . init ( ( KeyStore ) null ) ;
2023-11-10 07:30:22 +00:00
ssb . append ( " Trust provider: " ) . append ( tmf . getProvider ( ) . getName ( ) ) . append ( " \ r \ n " ) ;
ssb . append ( " Trust class: " ) . append ( tmf . getProvider ( ) . getClass ( ) . getName ( ) ) . append ( " \ r \ n " ) ;
ssb . append ( " Trust algorithm: " ) . append ( tmf . getAlgorithm ( ) ) . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
TrustManager [ ] tms = tmf . getTrustManagers ( ) ;
if ( tms ! = null )
for ( TrustManager tm : tms )
2023-11-10 07:30:22 +00:00
ssb . append ( " Trust manager: " ) . append ( tm . getClass ( ) . getName ( ) ) . append ( " \ r \ n " ) ;
ssb . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
sslContext . init ( null , tmf . getTrustManagers ( ) , null ) ;
SSLSocket socket = ( SSLSocket ) sslContext . getSocketFactory ( ) . createSocket ( ) ;
List < String > protocols = new ArrayList < > ( ) ;
protocols . addAll ( Arrays . asList ( socket . getEnabledProtocols ( ) ) ) ;
for ( String p : socket . getSupportedProtocols ( ) ) {
boolean enabled = protocols . contains ( p ) ;
if ( ! enabled )
ssb . append ( '(' ) ;
int start = ssb . length ( ) ;
ssb . append ( p ) ;
if ( ! enabled ) {
ssb . setSpan ( new StrikethroughSpan ( ) , start , ssb . length ( ) , 0 ) ;
ssb . append ( ')' ) ;
}
ssb . append ( " \ r \ n " ) ;
2022-02-23 14:45:51 +00:00
}
ssb . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
List < String > ciphers = new ArrayList < > ( ) ;
ciphers . addAll ( Arrays . asList ( socket . getEnabledCipherSuites ( ) ) ) ;
for ( String c : socket . getSupportedCipherSuites ( ) ) {
boolean enabled = ciphers . contains ( c ) ;
if ( ! enabled )
ssb . append ( '(' ) ;
int start = ssb . length ( ) ;
ssb . append ( c ) ;
if ( ! enabled ) {
ssb . setSpan ( new StrikethroughSpan ( ) , start , ssb . length ( ) , 0 ) ;
ssb . append ( ')' ) ;
}
ssb . append ( " \ r \ n " ) ;
2022-02-23 14:45:51 +00:00
}
ssb . append ( " \ r \ n " ) ;
2023-11-09 20:17:52 +00:00
} catch ( Throwable ex ) {
ssb . append ( ex . toString ( ) ) ;
2022-02-22 18:19:26 +00:00
}
ssb . setSpan ( new RelativeSizeSpan ( HtmlHelper . FONT_SMALL ) , 0 , ssb . length ( ) , 0 ) ;
return ssb ;
}
2019-05-12 17:14:34 +00:00
private static int write ( OutputStream os , String text ) throws IOException {
byte [ ] bytes = text . getBytes ( ) ;
os . write ( bytes ) ;
return bytes . length ;
}
2019-08-12 11:33:39 +00:00
private static long getFreeMem ( ) {
2019-05-22 13:41:54 +00:00
Runtime rt = Runtime . getRuntime ( ) ;
long used = ( rt . totalMemory ( ) - rt . freeMemory ( ) ) ;
long max = rt . maxMemory ( ) ;
return ( max - used ) ;
}
static int getFreeMemMb ( ) {
return ( int ) ( getFreeMem ( ) / 1024L / 1024L ) ;
}
2020-09-28 10:30:52 +00:00
static int getAvailableMb ( ) {
Runtime rt = Runtime . getRuntime ( ) ;
return ( int ) ( rt . maxMemory ( ) / 1024L / 1024L ) ;
}
2019-05-12 17:14:34 +00:00
static InternetAddress myAddress ( ) throws UnsupportedEncodingException {
2020-07-10 08:07:53 +00:00
return new InternetAddress ( " marcel+fairemail@faircode.eu " , " FairCode " , StandardCharsets . UTF_8 . name ( ) ) ;
2019-05-12 17:14:34 +00:00
}
2022-01-03 18:23:36 +00:00
static StringBuilder getSpans ( CharSequence text ) {
StringBuilder sb = new StringBuilder ( ) ;
TextUtils . dumpSpans ( text , new Printer ( ) {
@Override
public void println ( String x ) {
if ( sb . length ( ) > 0 )
sb . append ( ' ' ) ;
sb . append ( x . replace ( '\n' , '|' ) ) . append ( ']' ) ;
}
} , " [ " ) ;
return sb ;
}
2021-05-28 18:22:01 +00:00
}