@@ -250,6 +250,18 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
250250 if (INSTANCE == null ) INSTANCE = this
251251 relPackageName = this .packageName
252252 super .onCreate()
253+ var output = Shell .cmd(" echo $(id -u)" ).exec().out [0 ]
254+ if (output != null ) {
255+ output = output.trim { it <= ' ' }
256+ if (forceDebugLogging) Timber .d(" UID: %s" , output)
257+ if (output == " 0" ) {
258+ if (forceDebugLogging) Timber .d(" Root access granted" )
259+ setHasGottenRootAccess(true )
260+ } else {
261+ if (forceDebugLogging) Timber .d(" Root access or we're not uid 0. Current uid: %s" , output)
262+ setHasGottenRootAccess(false )
263+ }
264+ }
253265 if (! callbacksRegistered) {
254266 try {
255267 registerActivityLifecycleCallbacks(this )
@@ -260,7 +272,7 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
260272 }
261273 // Initialize Timber
262274 configTimber()
263- Timber .i(
275+ if (forceDebugLogging) Timber .i(
264276 " Starting AMM version %s (%d) - commit %s" ,
265277 BuildConfig .VERSION_NAME ,
266278 BuildConfig .VERSION_CODE ,
@@ -275,13 +287,13 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
275287 fileUtils.ensureCacheDirs()
276288 fileUtils.ensureURLHandler(this )
277289 }
278- if (BuildConfig . DEBUG ) Timber .d(" Initializing AMM" )
279- if (BuildConfig . DEBUG ) Timber .d(" Started from background: %s" , ! isInForeground)
280- if (BuildConfig . DEBUG ) Timber .d(" AMM is running in debug mode" )
290+ if (forceDebugLogging ) Timber .d(" Initializing AMM" )
291+ if (forceDebugLogging ) Timber .d(" Started from background: %s" , ! isInForeground)
292+ if (forceDebugLogging ) Timber .d(" AMM is running in debug mode" )
281293 // analytics
282- if (BuildConfig . DEBUG ) Timber .d(" Initializing countly" )
294+ if (forceDebugLogging ) Timber .d(" Initializing countly" )
283295 if (! analyticsAllowed()) {
284- if (BuildConfig . DEBUG ) Timber .d(" countly is not allowed" )
296+ if (forceDebugLogging ) Timber .d(" countly is not allowed" )
285297 } else {
286298 val config = CountlyConfig (
287299 this ,
@@ -344,9 +356,9 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
344356 fontRequestEmojiCompatConfig.setMetadataLoadStrategy(EmojiCompat .LOAD_STRATEGY_MANUAL )
345357 val emojiCompat = EmojiCompat .init (fontRequestEmojiCompatConfig)
346358 Thread ({
347- Timber .i(" Loading emoji compat..." )
359+ if (forceDebugLogging) Timber .i(" Loading emoji compat..." )
348360 emojiCompat.load()
349- Timber .i(" Emoji compat loaded!" )
361+ if (forceDebugLogging) Timber .i(" Emoji compat loaded!" )
350362 }, " Emoji compat init." ).start()
351363 }
352364 @Suppress(" KotlinConstantConditions" ) if ((BuildConfig .ANDROIDACY_CLIENT_ID == " " )) {
@@ -386,7 +398,7 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
386398 // make sure the directory exists
387399 if (! dataDir.exists()) {
388400 if (! dataDir.mkdirs()) {
389- if (BuildConfig . DEBUG ) Timber .w(
401+ if (forceDebugLogging ) Timber .w(
390402 " Failed to create directory %s" , dataDir
391403 )
392404 }
@@ -397,7 +409,7 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
397409 // create the directory if it doesn't exist
398410 if (! dataDir.exists()) {
399411 if (! dataDir.mkdirs()) {
400- if (BuildConfig . DEBUG ) Timber .w(" Failed to create directory %s" , dataDir)
412+ if (forceDebugLogging ) Timber .w(" Failed to create directory %s" , dataDir)
401413 }
402414 }
403415 }
@@ -422,12 +434,12 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
422434 val activityManager = this .getSystemService(ACTIVITY_SERVICE ) as ActivityManager
423435 val appProcesses = activityManager.runningAppProcesses
424436 if (appProcesses == null ) {
425- if (BuildConfig . DEBUG ) Timber .d(" appProcesses is null" )
437+ if (forceDebugLogging ) Timber .d(" appProcesses is null" )
426438 return false
427439 }
428440 val packageName = this .packageName
429441 for (appProcess in appProcesses) {
430- if (BuildConfig . DEBUG ) Timber .d(
442+ if (forceDebugLogging ) Timber .d(
431443 " Process: %s, Importance: %d" , appProcess.processName, appProcess.importance
432444 )
433445 if (appProcess.importance == RunningAppProcessInfo .IMPORTANCE_FOREGROUND && appProcess.processName == packageName) {
@@ -456,26 +468,37 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
456468 }
457469
458470 class ReleaseTree : Timber .Tree () {
471+ @SuppressLint(" LogNotTimber" )
459472 override fun log (priority : Int , tag : String? , message : String , t : Throwable ? ) {
460473 // basically silently drop all logs below error, and write the rest to logcat
461474 @Suppress(" NAME_SHADOWING" ) var message = message
462475 if (INSTANCE !! .isTainted) {
463476 // prepend [TAINTED] to the message
464477 message = " [TAINTED] $message "
465478 }
466- if (priority >= Log .ERROR ) {
467- if (t != null ) {
468- Log .println (priority, tag, message)
469- t.printStackTrace()
470- } else {
471- Log .println (priority, tag, message)
479+ if (forceDebugLogging) {
480+ if (priority >= Log .DEBUG ) {
481+ when (priority) {
482+ Log .DEBUG -> Log .d(tag, message, t)
483+ Log .INFO -> Log .i(tag, message, t)
484+ Log .WARN -> Log .w(tag, message, t)
485+ Log .ERROR -> Log .e(tag, message, t)
486+ Log .ASSERT -> Log .wtf(tag, message, t)
487+ }
488+ t?.printStackTrace()
489+ }
490+ } else {
491+ if (priority >= Log .ERROR ) {
492+ Log .e(tag, message, t)
472493 }
473494 }
474495 }
475496 }
476497
477498 companion object {
478499
500+ var forceDebugLogging: Boolean = BuildConfig .DEBUG || getSharedPreferences(" mmm" )?.getBoolean(" pref_force_debug_logging" , false ) ? : false
501+
479502 // Warning! Locales that don't exist will crash the app
480503 // Anything that is commented out is supported but the translation is not complete to at least 60%
481504 @JvmField
@@ -522,7 +545,7 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
522545 }
523546 // prewarm shell
524547 Shell .getShell {
525- // do nothing
548+ if (forceDebugLogging) Timber .d( " Shell prewarmed " )
526549 }
527550 val random = Random ()
528551 do {
@@ -574,8 +597,32 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
574597 mSharedPrefs!! [name] = sharedPreferences
575598 sharedPreferences
576599 } catch (e: Exception ) {
577- Timber .e(e, " Failed to create encrypted shared preferences" )
578- mContext!! .getSharedPreferences(name, MODE_PRIVATE )
600+ // try again five times, with a 250ms delay between each try. if we still can't get the shared preferences, throw an exception
601+ var i = 0
602+ while (i < 5 ) {
603+ try {
604+ Thread .sleep(250 )
605+ } catch (ignored: InterruptedException ) {
606+ }
607+ try {
608+ val masterKey =
609+ MasterKey .Builder (mContext!! ).setKeyScheme(MasterKey .KeyScheme .AES256_GCM )
610+ .build()
611+ val sharedPreferences = EncryptedSharedPreferences .create(
612+ mContext,
613+ name,
614+ masterKey,
615+ EncryptedSharedPreferences .PrefKeyEncryptionScheme .AES256_SIV ,
616+ EncryptedSharedPreferences .PrefValueEncryptionScheme .AES256_GCM
617+ )
618+ mSharedPrefs!! [name] = sharedPreferences
619+ return sharedPreferences
620+ } catch (e: Exception ) {
621+ Timber .e(e, " Failed to get shared preferences" )
622+ }
623+ i++
624+ }
625+ throw IllegalStateException (" Failed to get shared preferences" )
579626 }
580627 }
581628
@@ -683,7 +730,7 @@ class MainApplication : Application(), Configuration.Provider, ActivityLifecycle
683730 // should not have been shown in 14 days and only 1 in 5 chance
684731 val randChance = Random ().nextInt(5 )
685732 val lastShown = getSharedPreferences(" mmm" )!! .getLong(" last_feedback" , 0 )
686- if (BuildConfig . DEBUG ) Timber .d(" Last feedback shown: %d, randChance: %d" , lastShown, randChance)
733+ if (forceDebugLogging ) Timber .d(" Last feedback shown: %d, randChance: %d" , lastShown, randChance)
687734 return System .currentTimeMillis() - lastShown > 1209600000 && randChance == 0
688735 }
689736 }
0 commit comments