Created
April 28, 2022 20:09
-
-
Save DanielJette/98b8f8068b4036af5c190e28ceb50b80 to your computer and use it in GitHub Desktop.
Validate the bundle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.os.Bundle | |
import android.os.Parcelable | |
import android.util.Log | |
import androidx.annotation.VisibleForTesting | |
import com.shopify.foundation.extensions.parceledSize | |
import com.shopify.foundation.util.BuildConfig | |
private const val BUNDLE_SIZE_WARNING_THRESHOLD = 100000 | |
private const val LOG_TAG = "BundleValidator" | |
private const val BUNDLE_TAG = "INSTANCE_ID" | |
private const val BUNDLE_IGNORE = "BUNDLE_IGNORE" | |
@VisibleForTesting | |
class BundleTooLargeException(bundleSize: Int) : IllegalStateException( | |
"""\n\n | |
* There is too much data being saved to the Bundle. | |
* As a warning to developers, we have set a limit of $BUNDLE_SIZE_WARNING_THRESHOLD bytes in the bundle. | |
* This Bundle is currently saving approximately $bundleSize bytes. | |
* The Binder transaction buffer has a limited fixed size, currently 1MB, which is shared by all transactions in progress for the process. | |
* State must be simple and lightweight. For complex or large data you should use local persistence. | |
* If you are seeing this warning, please look in to using StatePersistenceHandle instead of SaveStateHandle. | |
* If you are seeing this warning and the activity does not use a StatePersistenceHandle instead or SaveStateHandle, override the onSaveInstanceState method and put a boolean with the key BUNDLE_IGNORE. | |
""".trimIndent() | |
) | |
/** | |
* Validate the bundle size if the bundle does not contain the BUNDLE_TAG and the BUNDLE_IGNORE. | |
* The BUNDLE_TAG is automatically | |
* set for all the activities that have a Flow Model with a StatePersistenceHandle instead of the SaveState Handle. | |
* The BUNDLE_IGNORE needs to be manually set on the onSavedInstanceState for the Activity if it does not use a flow model but | |
* still has a large bundle size due to a result sent by an external library(Merchant Login webview login is one of these cases). | |
*/ | |
fun Bundle.validateBundle() { | |
if (BuildConfig.DEBUG && !this.containsKey(BUNDLE_TAG) && !this.containsKey(BUNDLE_IGNORE)) { | |
val bundleSize = this.keySet().sumBy { | |
try { | |
(this[it] as? Parcelable)?.parceledSize ?: 0 | |
} catch (e: RuntimeException) { | |
// Getting the size of the net.openid.appauth.AuthorizationManagementActivity throws | |
// an exception since it has binder objects. Checking the size causes it to be | |
// unmarshalled causing this exception. | |
Log.e(LOG_TAG, "Unable to check size of SavedInstanceState, could not get size of key $it", e) | |
0 | |
} | |
} | |
if (bundleSize > BUNDLE_SIZE_WARNING_THRESHOLD) { | |
throw BundleTooLargeException(bundleSize) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment