Merge "Implement dark launch logic for sharesheet aiai model." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b4c0d6464e
@@ -414,6 +414,12 @@ public final class SystemUiDeviceConfigFlags {
|
||||
*/
|
||||
public static final String CHOOSER_TARGET_RANKING_ENABLED = "chooser_target_ranking_enabled";
|
||||
|
||||
/**
|
||||
* (boolean) Whether dark launch of remote prediction service is enabled.
|
||||
*/
|
||||
public static final String DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED =
|
||||
"dark_launch_remote_prediction_service_enabled";
|
||||
|
||||
/**
|
||||
* (boolean) Whether to enable pinch resizing for PIP.
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.ShellCallback;
|
||||
import android.util.Slog;
|
||||
@@ -179,7 +180,8 @@ public class AppPredictionManagerService extends
|
||||
Context ctx = getContext();
|
||||
if (!(ctx.checkCallingPermission(PACKAGE_USAGE_STATS) == PERMISSION_GRANTED
|
||||
|| mServiceNameResolver.isTemporary(userId)
|
||||
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid()))) {
|
||||
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())
|
||||
|| Binder.getCallingUid() == Process.SYSTEM_UID)) {
|
||||
|
||||
String msg = "Permission Denial: " + func + " from pid="
|
||||
+ Binder.getCallingPid()
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.internal.infra.AbstractRemoteService;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.infra.AbstractPerUserSystemService;
|
||||
@@ -55,6 +56,8 @@ public class AppPredictionPerUserService extends
|
||||
private static final String TAG = AppPredictionPerUserService.class.getSimpleName();
|
||||
private static final String PREDICT_USING_PEOPLE_SERVICE_PREFIX =
|
||||
"predict_using_people_service_";
|
||||
private static final String REMOTE_APP_PREDICTOR_KEY = "remote_app_predictor";
|
||||
|
||||
|
||||
@Nullable
|
||||
@GuardedBy("mLock")
|
||||
@@ -112,8 +115,16 @@ public class AppPredictionPerUserService extends
|
||||
@GuardedBy("mLock")
|
||||
public void onCreatePredictionSessionLocked(@NonNull AppPredictionContext context,
|
||||
@NonNull AppPredictionSessionId sessionId, @NonNull IBinder token) {
|
||||
final boolean usesPeopleService = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
|
||||
boolean usesPeopleService = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
|
||||
PREDICT_USING_PEOPLE_SERVICE_PREFIX + context.getUiSurface(), false);
|
||||
if (context.getExtras() != null
|
||||
&& context.getExtras().getBoolean(REMOTE_APP_PREDICTOR_KEY, false)
|
||||
&& DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED, false)
|
||||
) {
|
||||
// connect with remote AppPredictionService instead for dark launch
|
||||
usesPeopleService = false;
|
||||
}
|
||||
final boolean serviceExists = resolveService(sessionId, false,
|
||||
usesPeopleService, s -> s.onCreatePredictionSession(context, sessionId));
|
||||
if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
|
||||
|
||||
@@ -388,9 +388,11 @@ public class PeopleService extends SystemService {
|
||||
private Map<AppPredictionSessionId, SessionInfo> mSessions = new ArrayMap<>();
|
||||
|
||||
@Override
|
||||
public void onCreatePredictionSession(AppPredictionContext context,
|
||||
public void onCreatePredictionSession(AppPredictionContext appPredictionContext,
|
||||
AppPredictionSessionId sessionId) {
|
||||
mSessions.put(sessionId, new SessionInfo(context, mDataManager, sessionId.getUserId()));
|
||||
mSessions.put(sessionId,
|
||||
new SessionInfo(appPredictionContext, mDataManager, sessionId.getUserId(),
|
||||
getContext()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.UserIdInt;
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.app.prediction.IPredictionCallback;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.RemoteException;
|
||||
@@ -40,9 +41,9 @@ class SessionInfo {
|
||||
new RemoteCallbackList<>();
|
||||
|
||||
SessionInfo(AppPredictionContext predictionContext, DataManager dataManager,
|
||||
@UserIdInt int callingUserId) {
|
||||
@UserIdInt int callingUserId, Context context) {
|
||||
mAppTargetPredictor = AppTargetPredictor.create(predictionContext,
|
||||
this::updatePredictions, dataManager, callingUserId);
|
||||
this::updatePredictions, dataManager, callingUserId, context);
|
||||
}
|
||||
|
||||
void addCallback(IPredictionCallback callback) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.app.prediction.AppTargetEvent;
|
||||
import android.app.prediction.AppTargetId;
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.people.data.DataManager;
|
||||
@@ -43,10 +44,10 @@ public class AppTargetPredictor {
|
||||
/** Creates a {@link AppTargetPredictor} instance based on the prediction context. */
|
||||
public static AppTargetPredictor create(@NonNull AppPredictionContext predictionContext,
|
||||
@NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
|
||||
@NonNull DataManager dataManager, @UserIdInt int callingUserId) {
|
||||
@NonNull DataManager dataManager, @UserIdInt int callingUserId, Context context) {
|
||||
if (UI_SURFACE_SHARE.equals(predictionContext.getUiSurface())) {
|
||||
return new ShareTargetPredictor(
|
||||
predictionContext, updatePredictionsMethod, dataManager, callingUserId);
|
||||
return new ShareTargetPredictor(predictionContext, updatePredictionsMethod, dataManager,
|
||||
callingUserId, context);
|
||||
}
|
||||
return new AppTargetPredictor(
|
||||
predictionContext, updatePredictionsMethod, dataManager, callingUserId);
|
||||
@@ -124,6 +125,11 @@ public class AppTargetPredictor {
|
||||
callback.accept(targets);
|
||||
}
|
||||
|
||||
/** To be overridden by the subclass to recycle resources. */
|
||||
@WorkerThread
|
||||
void destroy() {
|
||||
}
|
||||
|
||||
AppPredictionContext getPredictionContext() {
|
||||
return mPredictionContext;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.server.people.prediction;
|
||||
|
||||
import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
|
||||
|
||||
import static java.util.Collections.reverseOrder;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -23,17 +25,23 @@ import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.annotation.WorkerThread;
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppPredictionManager;
|
||||
import android.app.prediction.AppPredictor;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.app.prediction.AppTargetEvent;
|
||||
import android.app.prediction.AppTargetId;
|
||||
import android.content.Context;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager.ShareShortcutInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.ChooserActivity;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.server.people.data.ConversationInfo;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.EventHistory;
|
||||
@@ -52,14 +60,27 @@ class ShareTargetPredictor extends AppTargetPredictor {
|
||||
|
||||
private static final String TAG = "ShareTargetPredictor";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String REMOTE_APP_PREDICTOR_KEY = "remote_app_predictor";
|
||||
private final IntentFilter mIntentFilter;
|
||||
private final AppPredictor mRemoteAppPredictor;
|
||||
|
||||
ShareTargetPredictor(@NonNull AppPredictionContext predictionContext,
|
||||
@NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
|
||||
@NonNull DataManager dataManager, @UserIdInt int callingUserId) {
|
||||
@NonNull DataManager dataManager,
|
||||
@UserIdInt int callingUserId, @NonNull Context context) {
|
||||
super(predictionContext, updatePredictionsMethod, dataManager, callingUserId);
|
||||
mIntentFilter = predictionContext.getExtras().getParcelable(
|
||||
ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY);
|
||||
if (DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED,
|
||||
false)) {
|
||||
predictionContext.getExtras().putBoolean(REMOTE_APP_PREDICTOR_KEY, true);
|
||||
mRemoteAppPredictor = context.createContextAsUser(UserHandle.of(callingUserId), 0)
|
||||
.getSystemService(AppPredictionManager.class)
|
||||
.createAppPredictionSession(predictionContext);
|
||||
} else {
|
||||
mRemoteAppPredictor = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Reports chosen history of direct/app share targets. */
|
||||
@@ -72,6 +93,9 @@ class ShareTargetPredictor extends AppTargetPredictor {
|
||||
if (mIntentFilter != null) {
|
||||
getDataManager().reportShareTargetEvent(event, mIntentFilter);
|
||||
}
|
||||
if (mRemoteAppPredictor != null) {
|
||||
mRemoteAppPredictor.notifyAppTargetEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides prediction on direct share targets */
|
||||
@@ -129,6 +153,15 @@ class ShareTargetPredictor extends AppTargetPredictor {
|
||||
callback.accept(appTargetList);
|
||||
}
|
||||
|
||||
/** Recycles resources. */
|
||||
@WorkerThread
|
||||
@Override
|
||||
void destroy() {
|
||||
if (mRemoteAppPredictor != null) {
|
||||
mRemoteAppPredictor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ShareTarget> getDirectShareTargets() {
|
||||
List<ShareTarget> shareTargets = new ArrayList<>();
|
||||
List<ShareShortcutInfo> shareShortcuts =
|
||||
|
||||
@@ -47,12 +47,14 @@ import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.test.TestLooper;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableContext;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -126,6 +128,10 @@ public final class PeopleServiceTest {
|
||||
.setPredictedTargetCount(APP_PREDICTION_TARGET_COUNT)
|
||||
.setExtras(new Bundle())
|
||||
.build();
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED,
|
||||
Boolean.toString(false),
|
||||
true /* makeDefault*/);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -22,13 +22,17 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anySet;
|
||||
import static org.mockito.Mockito.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppPredictionManager;
|
||||
import android.app.prediction.AppTarget;
|
||||
import android.app.prediction.AppTargetEvent;
|
||||
import android.app.prediction.AppTargetId;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -38,9 +42,11 @@ import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager.ShareShortcutInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Range;
|
||||
|
||||
import com.android.internal.app.ChooserActivity;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.server.people.data.ConversationInfo;
|
||||
import com.android.server.people.data.DataManager;
|
||||
import com.android.server.people.data.EventHistory;
|
||||
@@ -71,6 +77,14 @@ public final class ShareTargetPredictorTest {
|
||||
private static final String PACKAGE_3 = "pkg3";
|
||||
private static final String CLASS_1 = "cls1";
|
||||
private static final String CLASS_2 = "cls2";
|
||||
private static final AppTargetEvent APP_TARGET_EVENT =
|
||||
new AppTargetEvent.Builder(
|
||||
new AppTarget.Builder(
|
||||
new AppTargetId("cls1#pkg1"), PACKAGE_1, UserHandle.of(USER_ID)).build(),
|
||||
AppTargetEvent.ACTION_LAUNCH)
|
||||
.setLaunchLocation(ChooserActivity.LAUNCH_LOCATION_DIRECT_SHARE)
|
||||
.build();
|
||||
private static final IntentFilter INTENT_FILTER = IntentFilter.create("SEND", "text/plain");
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private DataManager mDataManager;
|
||||
@@ -102,17 +116,33 @@ public final class ShareTargetPredictorTest {
|
||||
when(mDataManager.getShareShortcuts(any(), anyInt())).thenReturn(mShareShortcuts);
|
||||
when(mDataManager.getPackage(PACKAGE_1, USER_ID)).thenReturn(mPackageData1);
|
||||
when(mDataManager.getPackage(PACKAGE_2, USER_ID)).thenReturn(mPackageData2);
|
||||
when(mContext.createContextAsUser(any(), any())).thenReturn(mContext);
|
||||
when(mContext.getSystemServiceName(AppPredictionManager.class)).thenReturn(
|
||||
Context.APP_PREDICTION_SERVICE);
|
||||
when(mContext.getSystemService(AppPredictionManager.class))
|
||||
.thenReturn(new AppPredictionManager(mContext));
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putObject(ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY,
|
||||
IntentFilter.create("SEND", "text/plain"));
|
||||
bundle.putObject(ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY, INTENT_FILTER);
|
||||
AppPredictionContext predictionContext = new AppPredictionContext.Builder(mContext)
|
||||
.setUiSurface(UI_SURFACE_SHARE)
|
||||
.setPredictedTargetCount(NUM_PREDICTED_TARGETS)
|
||||
.setExtras(bundle)
|
||||
.build();
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.DARK_LAUNCH_REMOTE_PREDICTION_SERVICE_ENABLED,
|
||||
Boolean.toString(true),
|
||||
true /* makeDefault*/);
|
||||
mPredictor = new ShareTargetPredictor(
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID);
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID, mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReportAppTargetEvent() {
|
||||
mPredictor.reportAppTargetEvent(APP_TARGET_EVENT);
|
||||
|
||||
verify(mDataManager, times(1))
|
||||
.reportShareTargetEvent(eq(APP_TARGET_EVENT), eq(INTENT_FILTER));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -240,7 +270,7 @@ public final class ShareTargetPredictorTest {
|
||||
.setExtras(new Bundle())
|
||||
.build();
|
||||
mPredictor = new ShareTargetPredictor(
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID);
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID, mContext);
|
||||
|
||||
mPredictor.predictTargets();
|
||||
|
||||
@@ -349,7 +379,7 @@ public final class ShareTargetPredictorTest {
|
||||
.setExtras(new Bundle())
|
||||
.build();
|
||||
mPredictor = new ShareTargetPredictor(
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID);
|
||||
predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID, mContext);
|
||||
AppTarget appTarget1 = new AppTarget.Builder(
|
||||
new AppTargetId("cls1#pkg1"), PACKAGE_1, UserHandle.of(USER_ID))
|
||||
.build();
|
||||
|
||||
Reference in New Issue
Block a user