1 /*
<lambda>null2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.sharetest
18
19 import android.app.PendingIntent
20 import android.content.ComponentName
21 import android.content.Context
22 import android.content.Intent
23 import android.graphics.drawable.Icon
24 import android.net.Uri
25 import android.os.Bundle
26 import android.service.chooser.ChooserAction
27 import android.service.chooser.ChooserTarget
28 import android.text.TextUtils
29 import androidx.core.os.bundleOf
30 import java.util.concurrent.atomic.AtomicInteger
31 import kotlin.math.roundToLong
32
33 const val REFINEMENT_ACTION = "com.android.sharetest.REFINEMENT"
34 private const val EXTRA_IS_INITIAL = "com.android.sharetest.IS_INITIAL"
35 private const val EXTRA_ID = "com.android.sharetest.ID"
36
37 fun createAlternateIntent(intent: Intent): Intent {
38 val text = buildString {
39 append("Shared URIs:")
40 intent.extraStream.forEach { append("\n * $it") }
41 }
42 return Intent(Intent.ACTION_SEND).apply { setText(text) }
43 }
44
Intentnull45 fun Intent.setText(text: CharSequence) {
46 if (TextUtils.isEmpty(type)) {
47 type = "text/plain"
48 }
49 putExtra(Intent.EXTRA_TEXT, text)
50 }
51
setModifyShareActionnull52 fun Intent.setModifyShareAction(context: Context) {
53 val modifyShareAction = createModifyShareAction(context, true, 0)
54 putExtra(Intent.EXTRA_CHOOSER_MODIFY_SHARE_ACTION, modifyShareAction)
55 }
56
Bundlenull57 fun Bundle.setModifyShareAction(context: Context, count: Int) {
58 val modifyShareAction = createModifyShareAction(context, false, count)
59 putParcelable(Intent.EXTRA_CHOOSER_MODIFY_SHARE_ACTION, modifyShareAction)
60 }
61
62 // Provide some gaussian noise around the preferred average latency
getLatencyMsnull63 fun getLatencyMs(avg: Long): Long {
64 // Using avg/4 as the standard deviation.
65 val noise = avg / 4 * random.nextGaussian()
66 return (avg + noise).roundToLong().coerceAtLeast(0)
67 }
68
getRandomFailurenull69 fun getRandomFailure(failureRate: Float): Boolean = random.nextFloat() < failureRate
70
71 private val random by lazy { java.util.Random() }
72
createModifyShareActionnull73 private fun createModifyShareAction(
74 context: Context,
75 isInitial: Boolean,
76 count: Int,
77 ): ChooserAction {
78 val pendingIntent =
79 PendingIntent.getBroadcast(
80 context,
81 1,
82 Intent(CustomActionFactory.BROADCAST_ACTION).apply { this.isInitial = isInitial },
83 PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT,
84 )
85 return ChooserAction.Builder(
86 Icon.createWithResource(context, R.drawable.testicon),
87 buildString {
88 append("Modify Share")
89 if (!isInitial) {
90 append(" (items: $count)")
91 }
92 },
93 pendingIntent,
94 )
95 .build()
96 }
97
98 val Intent.extraStream: List<Uri>
<lambda>null99 get() = buildList {
100 when (action) {
101 Intent.ACTION_SEND ->
102 getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let { add(it) }
103
104 Intent.ACTION_SEND_MULTIPLE ->
105 getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java)?.let { uris ->
106 for (uri in uris) {
107 if (uri != null) {
108 add(uri)
109 }
110 }
111 }
112 }
113 }
114
115 var Intent.isInitial: Boolean
116 set(value) {
117 putExtra(EXTRA_IS_INITIAL, value)
118 }
119 get() = getBooleanExtra(EXTRA_IS_INITIAL, true)
120
121 var Intent.id: Int
122 set(value) {
123 putExtra(EXTRA_ID, value)
124 }
125 get() = getIntExtra(EXTRA_ID, -1)
126
createCallerTargetnull127 fun createCallerTarget(context: Context, text: String) =
128 ChooserTarget(
129 "Caller Target",
130 Icon.createWithResource(context, R.drawable.launcher_icon),
131 1f,
132 ComponentName(context, CallerDirectTargetActivity::class.java),
133 bundleOf(Intent.EXTRA_TEXT to text),
134 )
135
136 private val refinementCounter = AtomicInteger(0)
137
138 fun createRefinementIntentSender(context: Context, isInitial: Boolean) =
139 PendingIntent.getBroadcast(
140 context,
141 1,
142 Intent(REFINEMENT_ACTION).apply {
143 setPackage(context.packageName)
144 this.isInitial = isInitial
145 id = refinementCounter.incrementAndGet()
146 },
147 PendingIntent.FLAG_MUTABLE or
148 PendingIntent.FLAG_CANCEL_CURRENT or
149 PendingIntent.FLAG_CANCEL_CURRENT,
150 )
151 .intentSender
152
153 private val resultIntentSenderCounter = AtomicInteger(0)
154
createResultIntentSendernull155 fun createResultIntentSender(context: Context) =
156 PendingIntent.getBroadcast(
157 context,
158 0,
159 Intent(context, ChosenComponentBroadcastReceiver::class.java).apply {
160 id = resultIntentSenderCounter.incrementAndGet()
161 },
162 PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,
163 )
164 .intentSender
165
166 val Any.hashId: String
167 get() = System.identityHashCode(this).toString(Character.MAX_RADIX)
168