Merge "Intercept chooser intents to use unbundled chooser (when enabled)" into tm-dev
This commit is contained in:
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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.server.pm;
|
||||||
|
|
||||||
|
import static com.android.server.wm.ActivityInterceptorCallback.INTENT_RESOLVER_ORDERED_ID;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.annotation.RequiresPermission;
|
||||||
|
import android.app.ActivityTaskManager;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||||
|
import com.android.server.LocalServices;
|
||||||
|
import com.android.server.wm.ActivityInterceptorCallback;
|
||||||
|
import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptorInfo;
|
||||||
|
import com.android.server.wm.ActivityTaskManagerInternal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service to register an {@code ActivityInterceptorCallback} that modifies any {@code Intent}
|
||||||
|
* that's being used to launch a user-space {@code ChooserActivity}, by adding
|
||||||
|
* EXTRA_PERMISSION_TOKEN, a Binder representing a single-use-only permission to invoke the
|
||||||
|
* #startActivityAsCaller() API (which normally isn't available in user-space); and setting the
|
||||||
|
* destination component to the delegated component when appropriate.
|
||||||
|
*/
|
||||||
|
public final class IntentResolverInterceptor {
|
||||||
|
private static final String TAG = "IntentResolverIntercept";
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
private boolean mUseDelegateChooser;
|
||||||
|
|
||||||
|
private final ActivityInterceptorCallback mActivityInterceptorCallback =
|
||||||
|
new ActivityInterceptorCallback() {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public ActivityInterceptResult intercept(ActivityInterceptorInfo info) {
|
||||||
|
if (mUseDelegateChooser && isChooserActivity(info)) {
|
||||||
|
return new ActivityInterceptResult(
|
||||||
|
modifyChooserIntent(info.intent),
|
||||||
|
info.checkedOptions);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public IntentResolverInterceptor(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start listening for intents and USE_DELEGATE_CHOOSER property changes.
|
||||||
|
*/
|
||||||
|
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
|
||||||
|
public void registerListeners() {
|
||||||
|
LocalServices.getService(ActivityTaskManagerInternal.class)
|
||||||
|
.registerActivityStartInterceptor(INTENT_RESOLVER_ORDERED_ID,
|
||||||
|
mActivityInterceptorCallback);
|
||||||
|
|
||||||
|
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||||
|
mContext.getMainExecutor(), properties -> updateUseDelegateChooser());
|
||||||
|
updateUseDelegateChooser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
|
||||||
|
private void updateUseDelegateChooser() {
|
||||||
|
mUseDelegateChooser = DeviceConfig.getBoolean(
|
||||||
|
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||||
|
SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Intent modifyChooserIntent(Intent intent) {
|
||||||
|
intent.setComponent(getUnbundledChooserComponentName());
|
||||||
|
addStartActivityPermissionTokenToIntent(intent, getUnbundledChooserComponentName());
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isChooserActivity(ActivityInterceptorInfo info) {
|
||||||
|
ComponentName targetComponent = new ComponentName(info.aInfo.packageName, info.aInfo.name);
|
||||||
|
|
||||||
|
return targetComponent.equals(getSystemChooserComponentName())
|
||||||
|
|| targetComponent.equals(getUnbundledChooserComponentName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Intent addStartActivityPermissionTokenToIntent(
|
||||||
|
Intent intent, ComponentName grantee) {
|
||||||
|
try {
|
||||||
|
intent.putExtra(
|
||||||
|
ActivityTaskManager.EXTRA_PERMISSION_TOKEN,
|
||||||
|
ActivityTaskManager.getService().requestStartActivityPermissionToken(grantee));
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.w(TAG, "Failed to add permission token to chooser intent");
|
||||||
|
}
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ComponentName getSystemChooserComponentName() {
|
||||||
|
return new ComponentName("android", "com.android.internal.app.ChooserActivity");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ComponentName getUnbundledChooserComponentName() {
|
||||||
|
return ComponentName.unflattenFromString(
|
||||||
|
Resources.getSystem().getString(R.string.config_chooserActivity));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -958,6 +958,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
private final ResolveIntentHelper mResolveIntentHelper;
|
private final ResolveIntentHelper mResolveIntentHelper;
|
||||||
private final DexOptHelper mDexOptHelper;
|
private final DexOptHelper mDexOptHelper;
|
||||||
private final SuspendPackageHelper mSuspendPackageHelper;
|
private final SuspendPackageHelper mSuspendPackageHelper;
|
||||||
|
private final IntentResolverInterceptor mIntentResolverInterceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidate the package info cache, which includes updating the cached computer.
|
* Invalidate the package info cache, which includes updating the cached computer.
|
||||||
@@ -1712,6 +1713,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
|
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
|
||||||
|
|
||||||
|
mIntentResolverInterceptor = null;
|
||||||
|
|
||||||
registerObservers(false);
|
registerObservers(false);
|
||||||
invalidatePackageInfoCache();
|
invalidatePackageInfoCache();
|
||||||
}
|
}
|
||||||
@@ -2240,6 +2243,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
|
mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
|
||||||
|
|
||||||
|
mIntentResolverInterceptor = new IntentResolverInterceptor(mContext);
|
||||||
|
|
||||||
Slog.i(TAG, "Fix for b/169414761 is applied");
|
Slog.i(TAG, "Fix for b/169414761 is applied");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6397,6 +6402,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
|||||||
|
|
||||||
// Prune unused static shared libraries which have been cached a period of time
|
// Prune unused static shared libraries which have been cached a period of time
|
||||||
schedulePruneUnusedStaticSharedLibraries(false /* delay */);
|
schedulePruneUnusedStaticSharedLibraries(false /* delay */);
|
||||||
|
|
||||||
|
// TODO(b/222706900): Remove this intent interceptor before T launch
|
||||||
|
if (mIntentResolverInterceptor != null) {
|
||||||
|
mIntentResolverInterceptor.registerListeners();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public abstract class ActivityInterceptorCallback {
|
|||||||
@IntDef(suffix = { "_ORDERED_ID" }, value = {
|
@IntDef(suffix = { "_ORDERED_ID" }, value = {
|
||||||
FIRST_ORDERED_ID,
|
FIRST_ORDERED_ID,
|
||||||
PERMISSION_POLICY_ORDERED_ID,
|
PERMISSION_POLICY_ORDERED_ID,
|
||||||
|
INTENT_RESOLVER_ORDERED_ID,
|
||||||
VIRTUAL_DEVICE_SERVICE_ORDERED_ID,
|
VIRTUAL_DEVICE_SERVICE_ORDERED_ID,
|
||||||
LAST_ORDERED_ID // Update this when adding new ids
|
LAST_ORDERED_ID // Update this when adding new ids
|
||||||
})
|
})
|
||||||
@@ -74,6 +75,11 @@ public abstract class ActivityInterceptorCallback {
|
|||||||
*/
|
*/
|
||||||
public static final int PERMISSION_POLICY_ORDERED_ID = 1;
|
public static final int PERMISSION_POLICY_ORDERED_ID = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier for {@link com.android.server.pm.IntentResolverInterceptor}.
|
||||||
|
*/
|
||||||
|
public static final int INTENT_RESOLVER_ORDERED_ID = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier for {@link com.android.server.companion.virtual.VirtualDeviceManagerService}
|
* The identifier for {@link com.android.server.companion.virtual.VirtualDeviceManagerService}
|
||||||
* interceptor.
|
* interceptor.
|
||||||
|
|||||||
Reference in New Issue
Block a user