diff options
| author | 2024-01-30 20:06:34 +0000 | |
|---|---|---|
| committer | 2024-01-30 20:06:34 +0000 | |
| commit | bd5caa0531d029d5215df0cab98d62c73b8f6d7e (patch) | |
| tree | fd5c5580fbaad454178feb38e6df9a08d1a07cd2 /java/src | |
| parent | b2bb4464ee586cfb3d8da41bab7f2895dcbb6808 (diff) | |
| parent | f0c6a508f930c7dab1ec95fa6b322abdc6609bbe (diff) | |
Merge "Rename CallerInfo -> ActivityLaunch and inject" into main
Diffstat (limited to 'java/src')
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ChooserActivity.java | 30 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ResolverActivity.java | 32 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ext/CreationExtrasExt.kt | 31 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ext/ParcelExt.kt | 27 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ui/model/ActivityLaunch.kt (renamed from java/src/com/android/intentresolver/v2/ui/model/CallerInfo.kt) | 46 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ui/model/ActivityLaunchModule.kt | 40 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt | 16 | ||||
| -rw-r--r-- | java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt | 17 |
8 files changed, 180 insertions, 59 deletions
diff --git a/java/src/com/android/intentresolver/v2/ChooserActivity.java b/java/src/com/android/intentresolver/v2/ChooserActivity.java index 95d9ea18..c1184a80 100644 --- a/java/src/com/android/intentresolver/v2/ChooserActivity.java +++ b/java/src/com/android/intentresolver/v2/ChooserActivity.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE import static androidx.lifecycle.LifecycleKt.getCoroutineScope; +import static com.android.intentresolver.v2.ext.CreationExtrasExtKt.addDefaultArgs; import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED; import static com.android.internal.util.LatencyTracker.ACTION_LOAD_SHARE_SHEET; @@ -75,7 +76,6 @@ import android.stats.devicepolicy.DevicePolicyEnums; import android.text.TextUtils; import android.util.Log; import android.util.Slog; -import android.util.SparseArray; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -95,7 +95,6 @@ import androidx.annotation.MainThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; -import androidx.lifecycle.SavedStateHandleSupport; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.viewmodel.CreationExtras; import androidx.recyclerview.widget.GridLayoutManager; @@ -149,7 +148,7 @@ import com.android.intentresolver.v2.platform.AppPredictionAvailable; import com.android.intentresolver.v2.platform.ImageEditor; import com.android.intentresolver.v2.platform.NearbyShare; import com.android.intentresolver.v2.ui.ActionTitle; -import com.android.intentresolver.v2.ui.model.CallerInfo; +import com.android.intentresolver.v2.ui.model.ActivityLaunch; import com.android.intentresolver.v2.ui.model.ChooserRequest; import com.android.intentresolver.v2.ui.viewmodel.ChooserViewModel; import com.android.intentresolver.widget.ImagePreviewView; @@ -164,6 +163,7 @@ import com.google.common.collect.ImmutableList; import dagger.hilt.android.AndroidEntryPoint; +import kotlin.Pair; import kotlin.Unit; import java.util.ArrayList; @@ -265,6 +265,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements private static final int SCROLL_STATUS_SCROLLING_VERTICAL = 1; private static final int SCROLL_STATUS_SCROLLING_HORIZONTAL = 2; + @Inject public ActivityLaunch mActivityLaunch; @Inject public FeatureFlags mFeatureFlags; @Inject public EventLog mEventLog; @Inject @AppPredictionAvailable public boolean mAppPredictionAvailable; @@ -332,20 +333,21 @@ public class ChooserActivity extends Hilt_ChooserActivity implements @NonNull @Override public CreationExtras getDefaultViewModelCreationExtras() { - CreationExtras extras = super.getDefaultViewModelCreationExtras(); - // Inserts a CallerInfo into the Bundle at stored at DEFAULT_ARGS_KEY - Bundle defaultArgs = requireNonNull(extras.get(SavedStateHandleSupport.DEFAULT_ARGS_KEY)); - defaultArgs.putParcelable(CallerInfo.SAVED_STATE_HANDLE_KEY, - new CallerInfo(getLaunchedFromUid(), - getLaunchedFromPackage(), - requireNonNull(getReferrer()))); - return extras; + return addDefaultArgs( + super.getDefaultViewModelCreationExtras(), + new Pair<>(ActivityLaunch.ACTIVITY_LAUNCH_KEY, mActivityLaunch)); } @Override protected final void onCreate(Bundle savedInstanceState) { - Log.d(TAG, "onCreate"); super.onCreate(savedInstanceState); + Log.i(TAG, "onCreate"); + Log.i(TAG, "activityLaunch=" + mActivityLaunch.toString()); + int callerUid = mActivityLaunch.getFromUid(); + if (callerUid < 0 || UserHandle.isIsolated(callerUid)) { + Log.e(TAG, "Can't start a resolver from uid " + callerUid); + finish(); + } setTheme(R.style.Theme_DeviceDefault_Chooser); Tracer.INSTANCE.markLaunched(); mViewModel = new ViewModelProvider(this).get(ChooserViewModel.class); @@ -824,7 +826,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements } } catch (RuntimeException e) { Slog.wtf(TAG, - "Unable to launch as uid " + requireAnnotatedUserHandles().userIdOfCallingApp + "Unable to launch as uid " + mActivityLaunch.getFromUid() + " package " + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } @@ -2103,7 +2105,7 @@ public class ChooserActivity extends Hilt_ChooserActivity implements mPackageManager, mLogic.getTargetIntent(), mLogic.getReferrerPackageName(), - requireAnnotatedUserHandles().userIdOfCallingApp, + mActivityLaunch.getFromUid(), resolverComparator, getQueryIntentsUser(userHandle)); } diff --git a/java/src/com/android/intentresolver/v2/ResolverActivity.java b/java/src/com/android/intentresolver/v2/ResolverActivity.java index 55e698a6..a308ea14 100644 --- a/java/src/com/android/intentresolver/v2/ResolverActivity.java +++ b/java/src/com/android/intentresolver/v2/ResolverActivity.java @@ -24,6 +24,7 @@ import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_S import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static com.android.intentresolver.v2.ext.CreationExtrasExtKt.addDefaultArgs; import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED; import static java.util.Collections.emptyList; @@ -83,6 +84,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.viewmodel.CreationExtras; import androidx.viewpager.widget.ViewPager; import com.android.intentresolver.AnnotatedUserHandles; @@ -109,6 +111,7 @@ import com.android.intentresolver.v2.emptystate.NoCrossProfileEmptyStateProvider import com.android.intentresolver.v2.emptystate.WorkProfilePausedEmptyStateProvider; import com.android.intentresolver.v2.ext.IntentExtKt; import com.android.intentresolver.v2.ui.ActionTitle; +import com.android.intentresolver.v2.ui.model.ActivityLaunch; import com.android.intentresolver.widget.ResolverDrawerLayout; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; @@ -119,6 +122,7 @@ import com.google.common.collect.ImmutableList; import dagger.hilt.android.AndroidEntryPoint; +import kotlin.Pair; import kotlin.Unit; import java.util.ArrayList; @@ -140,6 +144,7 @@ import javax.inject.Inject; public class ResolverActivity extends Hilt_ResolverActivity implements ResolverListAdapter.ResolverListCommunicator { + @Inject public ActivityLaunch mActivityLaunch; @Inject public DevicePolicyResources mDevicePolicyResources; @Inject public IntentForwarding mIntentForwarding; @@ -235,10 +240,26 @@ public class ResolverActivity extends Hilt_ResolverActivity implements this::onWorkProfileStatusUpdated); } + @NonNull + @Override + public CreationExtras getDefaultViewModelCreationExtras() { + return addDefaultArgs( + super.getDefaultViewModelCreationExtras(), + new Pair<>(ActivityLaunch.ACTIVITY_LAUNCH_KEY, mActivityLaunch)); + } + @Override protected final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(R.style.Theme_DeviceDefault_Resolver); + Log.i(TAG, "onCreate"); + Log.i(TAG, "activityLaunch=" + mActivityLaunch.toString()); + int callerUid = mActivityLaunch.getFromUid(); + if (callerUid < 0 || UserHandle.isIsolated(callerUid)) { + Log.e(TAG, "Can't start a resolver from uid " + callerUid); + finish(); + } + mLogic = createActivityLogic(); mResolvingHome = IntentExtKt.isHomeIntent(getIntent()); mTargetDataLoader = new DefaultTargetDataLoader( @@ -256,13 +277,6 @@ public class ResolverActivity extends Hilt_ResolverActivity implements Intent intent = mLogic.getTargetIntent(); List<Intent> initialIntents = mLogic.getInitialIntents(); - // Calling UID did not have valid permissions - if (mLogic.getAnnotatedUserHandles() == null) { - finish(); - return; - } - - // The last argument of createResolverListAdapter is whether to do special handling // of the last used choice to highlight it in the list. We need to always // turn this off when running under voice interaction, since it results in @@ -760,7 +774,7 @@ public class ResolverActivity extends Hilt_ResolverActivity implements getPackageManager(), mLogic.getTargetIntent(), mLogic.getReferrerPackageName(), - requireAnnotatedUserHandles().userIdOfCallingApp, + mActivityLaunch.getFromUid(), resolverComparator, getQueryIntentsUser(userHandle)); } @@ -1486,7 +1500,7 @@ public class ResolverActivity extends Hilt_ResolverActivity implements } } catch (RuntimeException e) { Slog.wtf(TAG, - "Unable to launch as uid " + requireAnnotatedUserHandles().userIdOfCallingApp + "Unable to launch as uid " + mActivityLaunch.getFromUid() + " package " + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } diff --git a/java/src/com/android/intentresolver/v2/ext/CreationExtrasExt.kt b/java/src/com/android/intentresolver/v2/ext/CreationExtrasExt.kt new file mode 100644 index 00000000..ebd613f1 --- /dev/null +++ b/java/src/com/android/intentresolver/v2/ext/CreationExtrasExt.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.v2.ext + +import android.os.Bundle +import android.os.Parcelable +import androidx.lifecycle.DEFAULT_ARGS_KEY +import androidx.lifecycle.viewmodel.CreationExtras + +/** Adds one or more key-value pairs to the default Args bundle in this extras instance. */ +fun CreationExtras.addDefaultArgs(vararg values: Pair<String, Parcelable>): CreationExtras { + val defaultArgs: Bundle = get(DEFAULT_ARGS_KEY) ?: Bundle() + for ((key, value) in values) { + defaultArgs.putParcelable(key, value) + } + return this +} diff --git a/java/src/com/android/intentresolver/v2/ext/ParcelExt.kt b/java/src/com/android/intentresolver/v2/ext/ParcelExt.kt new file mode 100644 index 00000000..b0ec97f4 --- /dev/null +++ b/java/src/com/android/intentresolver/v2/ext/ParcelExt.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.v2.ext + +import android.os.Parcel + +inline fun <reified T> Parcel.requireParcelable(): T { + return requireNotNull(readParcelable<T>()) { "A non-value required from this parcel was null!" } +} + +inline fun <reified T> Parcel.readParcelable(): T? { + return readParcelable(T::class.java.classLoader, T::class.java) +} diff --git a/java/src/com/android/intentresolver/v2/ui/model/CallerInfo.kt b/java/src/com/android/intentresolver/v2/ui/model/ActivityLaunch.kt index 9addeef2..fd25ea42 100644 --- a/java/src/com/android/intentresolver/v2/ui/model/CallerInfo.kt +++ b/java/src/com/android/intentresolver/v2/ui/model/ActivityLaunch.kt @@ -15,45 +15,51 @@ */ package com.android.intentresolver.v2.ui.model +import android.content.Intent import android.net.Uri import android.os.Parcel import android.os.Parcelable +import com.android.intentresolver.v2.ext.readParcelable +import com.android.intentresolver.v2.ext.requireParcelable -data class CallerInfo( - val launchedFromUid: Int, - val launchedFomPackage: String?, - /* logged to metrics, forwarded to outgoing intent */ - val referrer: Uri +/** Contains Activity-scope information about the state at launch time. */ +data class ActivityLaunch( + /** The [Intent] received by the app */ + val intent: Intent, + /** The identifier for the sending app and user */ + val fromUid: Int, + /** The package of the sending app */ + val fromPackage: String?, + /** The referrer as supplied to the activity. */ + val referrer: Uri? ) : Parcelable { constructor( source: Parcel ) : this( - launchedFromUid = source.readInt(), - launchedFomPackage = source.readString(), - checkNotNull(source.readParcelable()) + intent = source.requireParcelable(), + fromUid = source.readInt(), + fromPackage = source.readString(), + referrer = source.readParcelable() ) override fun describeContents() = 0 /* flags */ override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeInt(launchedFromUid) - dest.writeString(launchedFomPackage) - dest.writeParcelable(referrer, 0) + dest.writeParcelable(intent, flags) + dest.writeInt(fromUid) + dest.writeString(fromPackage) + dest.writeParcelable(referrer, flags) } companion object { - const val SAVED_STATE_HANDLE_KEY = "com.android.intentresolver.CALLER_INFO" + const val ACTIVITY_LAUNCH_KEY = "com.android.intentresolver.ACTIVITY_LAUNCH" - @JvmStatic + @JvmField @Suppress("unused") val CREATOR = - object : Parcelable.Creator<CallerInfo> { - override fun newArray(size: Int) = arrayOfNulls<CallerInfo>(size) - override fun createFromParcel(source: Parcel) = CallerInfo(source) + object : Parcelable.Creator<ActivityLaunch> { + override fun newArray(size: Int) = arrayOfNulls<ActivityLaunch>(size) + override fun createFromParcel(source: Parcel) = ActivityLaunch(source) } } } - -inline fun <reified T> Parcel.readParcelable(): T? { - return readParcelable(T::class.java.classLoader, T::class.java) -} diff --git a/java/src/com/android/intentresolver/v2/ui/model/ActivityLaunchModule.kt b/java/src/com/android/intentresolver/v2/ui/model/ActivityLaunchModule.kt new file mode 100644 index 00000000..3311467e --- /dev/null +++ b/java/src/com/android/intentresolver/v2/ui/model/ActivityLaunchModule.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.intentresolver.v2.ui.model + +import android.app.Activity +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.components.ActivityComponent +import dagger.hilt.android.scopes.ActivityScoped + +@Module +@InstallIn(ActivityComponent::class) +object ActivityLaunchModule { + + @Provides + @ActivityScoped + fun callerInfo(activity: Activity): ActivityLaunch { + return ActivityLaunch( + activity.intent, + activity.launchedFromUid, + activity.launchedFromPackage, + activity.referrer + ) + } +} diff --git a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt index 6878be5f..33868aaf 100644 --- a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt +++ b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserRequestReader.kt @@ -44,10 +44,11 @@ import com.android.intentresolver.R import com.android.intentresolver.util.hasValidIcon import com.android.intentresolver.v2.ext.hasAction import com.android.intentresolver.v2.ext.ifMatch -import com.android.intentresolver.v2.ui.model.CallerInfo +import com.android.intentresolver.v2.ui.model.ActivityLaunch import com.android.intentresolver.v2.ui.model.ChooserRequest import com.android.intentresolver.v2.ui.model.MAX_CHOOSER_ACTIONS import com.android.intentresolver.v2.ui.model.MAX_INITIAL_INTENTS +import com.android.intentresolver.v2.validation.ValidationResult import com.android.intentresolver.v2.validation.types.IntentOrUri import com.android.intentresolver.v2.validation.types.array import com.android.intentresolver.v2.validation.types.value @@ -61,8 +62,10 @@ internal fun Intent.maybeAddSendActionFlags() = addFlags(FLAG_ACTIVITY_MULTIPLE_TASK) } -fun readChooserRequest(callerInfo: CallerInfo, source: (String) -> Any?) = - validateFrom(source) { +fun readChooserRequest(launch: ActivityLaunch): ValidationResult<ChooserRequest> { + val extras = launch.intent.extras ?: Bundle() + @Suppress("DEPRECATION") + return validateFrom(extras::get) { val targetIntent = required(IntentOrUri(EXTRA_INTENT)).maybeAddSendActionFlags() val isSendAction = targetIntent.hasAction(ACTION_SEND, ACTION_SEND_MULTIPLE) @@ -118,7 +121,7 @@ fun readChooserRequest(callerInfo: CallerInfo, source: (String) -> Any?) = val modifyShareAction = optional(value<ChooserAction>(EXTRA_CHOOSER_MODIFY_SHARE_ACTION)) - val referrerFillIn = Intent().putExtra(EXTRA_REFERRER, callerInfo.referrer) + val referrerFillIn = Intent().putExtra(EXTRA_REFERRER, launch.referrer) ChooserRequest( targetIntent = targetIntent, @@ -126,8 +129,8 @@ fun readChooserRequest(callerInfo: CallerInfo, source: (String) -> Any?) = isSendActionTarget = isSendAction, targetType = targetIntent.type, launchedFromPackage = - requireNotNull(callerInfo.launchedFomPackage) { - "launchedFromPackage was null, See Activity.getLaunchedFromPackage()" + requireNotNull(launch.fromPackage) { + "launch.fromPackage was null, See Activity.getLaunchedFromPackage()" }, title = customTitle, defaultTitleResource = defaultTitleResource, @@ -146,6 +149,7 @@ fun readChooserRequest(callerInfo: CallerInfo, source: (String) -> Any?) = shareTargetFilter = targetIntent.toShareTargetFilter() ) } +} private fun Intent.toShareTargetFilter(): IntentFilter? { return type?.let { diff --git a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt index 663235ca..17b1e664 100644 --- a/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt +++ b/java/src/com/android/intentresolver/v2/ui/viewmodel/ChooserViewModel.kt @@ -18,7 +18,8 @@ package com.android.intentresolver.v2.ui.viewmodel import android.util.Log import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel -import com.android.intentresolver.v2.ui.model.CallerInfo +import com.android.intentresolver.v2.ui.model.ActivityLaunch +import com.android.intentresolver.v2.ui.model.ActivityLaunch.Companion.ACTIVITY_LAUNCH_KEY import com.android.intentresolver.v2.ui.model.ChooserRequest import com.android.intentresolver.v2.validation.ValidationResult import dagger.hilt.android.lifecycle.HiltViewModel @@ -27,19 +28,15 @@ import javax.inject.Inject private const val TAG = "ChooserViewModel" @HiltViewModel -class ChooserViewModel -@Inject -constructor( - private val args: SavedStateHandle, -) : ViewModel() { +class ChooserViewModel @Inject constructor(args: SavedStateHandle) : ViewModel() { - private val callerInfo: CallerInfo = - requireNotNull(args[CallerInfo.SAVED_STATE_HANDLE_KEY]) { - "CallerInfo missing in SavedStateHandle! (${CallerInfo.SAVED_STATE_HANDLE_KEY})" + private val mActivityLaunch: ActivityLaunch = + requireNotNull(args[ACTIVITY_LAUNCH_KEY]) { + "ActivityLaunch missing in SavedStateHandle! ($ACTIVITY_LAUNCH_KEY)" } /** The result of reading and validating the inputs provided in savedState. */ - private val status: ValidationResult<ChooserRequest> = readChooserRequest(callerInfo, args::get) + private val status: ValidationResult<ChooserRequest> = readChooserRequest(mActivityLaunch) val chooserRequest: ChooserRequest by lazy { status.getOrThrow() } |