• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.onboarding.bedsteadonboarding.activities
2 
3 import android.content.Context
4 import android.content.Intent
5 import android.os.Build
6 import android.os.Bundle
7 import android.util.Log
8 import androidx.activity.ComponentActivity
9 import com.android.onboarding.bedsteadonboarding.permissions.TestPermissions
10 import com.android.onboarding.bedsteadonboarding.providers.ConfigProviderUtil
11 
12 /**
13  * It is an activity whose exported value is always set as true. It's purpose is to launch another
14  * activity of the same app whose exported value is set as false. Every onboarding app would have
15  * this activity added via dependency on bedstead-onboarding.
16  */
17 class TrampolineActivity : ComponentActivity() {
18 
onCreatenull19   override fun onCreate(savedInstanceState: Bundle?) {
20     super.onCreate(savedInstanceState)
21     if (!hasPermission()) {
22       Log.e(TAG, "Unauthorized request for creating TrampolineActivity ")
23       finish()
24       return
25     }
26 
27     val nodeIntent =
28       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
29         intent.getParcelableExtra(EXTRA_NODE_START_INTENT_KEY, Intent::class.java)
30       } else {
31         intent.getParcelableExtra(EXTRA_NODE_START_INTENT_KEY)
32       }
33 
34     if (nodeIntent != null) {
35       startActivity(nodeIntent)
36     } else {
37       Log.e(TAG, NODE_NOT_LAUNCHED_ERROR_MSG)
38     }
39     finish()
40   }
41 
42   /**
43    * Returns true if either the code is triggered by Robolectric or else there is some test
44    * configuration set by Test Process and the caller is instrumented. It will always return false
45    * when it is called in production.
46    */
hasPermissionnull47   private fun hasPermission(): Boolean {
48     return when {
49       requireRobolectric() -> true
50       isTestConfigSet(context = this) -> {
51         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
52           return TestPermissions.uidIsInstrumented(this, launchedFromUid)
53         } else {
54           return true
55         }
56       }
57       else -> false
58     }
59   }
60 
requireRobolectricnull61   private fun requireRobolectric() = "robolectric" == Build.FINGERPRINT
62 
63   /**
64    * Returns if the test configuration has been set. It will always return false when it is called
65    * in production.
66    */
67   private fun isTestConfigSet(context: Context): Boolean {
68     val uri = ConfigProviderUtil.getTestConfigUri(context)
69     val cursor =
70       context.contentResolver.query(
71         uri,
72         arrayOf(ConfigProviderUtil.TEST_NODE_CLASS_COLUMN),
73         /* selection= */ null,
74         /* selectionArgs= */ null,
75         /* sortOrder= */ null,
76         /* cancellationSignal= */ null,
77       ) ?: return false
78     return cursor.use { it.moveToFirst() } // Returns if there is first record
79   }
80 
81   companion object {
82     private const val EXTRA_NODE_START_INTENT_KEY =
83       "com.android.onboarding.bedsteadonboarding.activities.extra.NODE_START_INTENT"
84     private const val NODE_NOT_LAUNCHED_ERROR_MSG = "Couldn't launch node as intent is null"
85     private const val TAG = "TrampolineActivity"
86   }
87 }
88