Adding a utility class to listen for app launches
Change-Id: I62e82a6e04b7101773d98c6e7aec574facd053fe
This commit is contained in:
parent
4397d8d5ea
commit
369212aed9
|
@ -70,6 +70,7 @@
|
|||
<string name="instant_app_resolver_class" translatable="false"></string>
|
||||
<string name="main_process_initializer_class" translatable="false"></string>
|
||||
<string name="system_shortcut_factory_class" translatable="false"></string>
|
||||
<string name="app_launch_tracker_class" translatable="false"></string>
|
||||
|
||||
<!-- Package name of the default wallpaper picker. -->
|
||||
<string name="wallpaper_picker_package" translatable="false"></string>
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_SEARCH;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
|
@ -32,10 +34,13 @@ import android.widget.Toast;
|
|||
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.shortcuts.DeepShortcutManager;
|
||||
import com.android.launcher3.uioverrides.DisplayRotationListener;
|
||||
import com.android.launcher3.uioverrides.WallpaperColorInfo;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Extension of BaseActivity allowing support for drag-n-drop
|
||||
*/
|
||||
|
@ -148,7 +153,8 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
|
||||
public abstract ActivityOptions getActivityLaunchOptions(View v);
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) {
|
||||
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
|
@ -169,13 +175,17 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
&& !((ShortcutInfo) item).isPromise();
|
||||
if (isShortcut) {
|
||||
// Shortcuts need some special checks due to legacy reasons.
|
||||
startShortcutIntentSafely(intent, optsBundle, item);
|
||||
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer);
|
||||
} else if (user == null || user.equals(Process.myUserHandle())) {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
|
||||
Process.myUserHandle(), sourceContainer);
|
||||
} else {
|
||||
LauncherAppsCompat.getInstance(this).startActivityForProfile(
|
||||
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(), user,
|
||||
sourceContainer);
|
||||
}
|
||||
getUserEventDispatcher().logAppLaunch(v, intent);
|
||||
getStatsLogManager().logAppLaunch(v, intent);
|
||||
|
@ -187,7 +197,8 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
return false;
|
||||
}
|
||||
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
|
||||
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info,
|
||||
@Nullable String sourceContainer) {
|
||||
try {
|
||||
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
|
||||
try {
|
||||
|
@ -202,6 +213,8 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
|||
String packageName = intent.getPackage();
|
||||
DeepShortcutManager.getInstance(this).startShortcut(
|
||||
packageName, id, intent.getSourceBounds(), optsBundle, info.user);
|
||||
AppLaunchTracker.INSTANCE.get(this).onStartShortcut(packageName, id, info.user,
|
||||
sourceContainer);
|
||||
} else {
|
||||
// Could be launching some bookkeeping activity
|
||||
startActivity(intent, optsBundle);
|
||||
|
|
|
@ -97,6 +97,7 @@ import com.android.launcher3.logging.FileLog;
|
|||
import com.android.launcher3.logging.StatsLogUtils;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.notification.NotificationListener;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
|
@ -694,7 +695,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
if (grantResults.length > 0
|
||||
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
startActivitySafely(v, intent, null);
|
||||
startActivitySafely(v, intent, null, null);
|
||||
} else {
|
||||
// TODO: Show a snack bar with link to settings
|
||||
Toast.makeText(this, getString(R.string.msg_no_phone_permission,
|
||||
|
@ -798,6 +799,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
getUserEventDispatcher().startSession();
|
||||
|
||||
UiFactory.onLauncherStateOrResumeChanged(this);
|
||||
AppLaunchTracker.INSTANCE.get(this).onReturnedToHome();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1652,8 +1654,9 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
}
|
||||
}
|
||||
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
|
||||
boolean success = super.startActivitySafely(v, intent, item);
|
||||
public boolean startActivitySafely(View v, Intent intent, ItemInfo item,
|
||||
@Nullable String sourceContainer) {
|
||||
boolean success = super.startActivitySafely(v, intent, item, sourceContainer);
|
||||
if (success && v instanceof BubbleTextView) {
|
||||
// This is set to the view that launched the activity that navigated the user away
|
||||
// from launcher. Since there is no callback for when the activity has finished
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.android.launcher3.Launcher;
|
|||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
@ -263,12 +264,8 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
|
|||
case VIEW_TYPE_SEARCH_MARKET:
|
||||
View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
|
||||
parent, false);
|
||||
searchMarketView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mLauncher.startActivitySafely(v, mMarketSearchIntent, null);
|
||||
}
|
||||
});
|
||||
searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
|
||||
v, mMarketSearchIntent, null, AppLaunchTracker.CONTAINER_SEARCH));
|
||||
return new ViewHolder(searchMarketView);
|
||||
case VIEW_TYPE_ALL_APPS_DIVIDER:
|
||||
return new ViewHolder(mLayoutInflater.inflate(
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.widget.TextView.OnEditorActionListener;
|
|||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
|
@ -111,7 +112,8 @@ public class AllAppsSearchBarController
|
|||
return false;
|
||||
}
|
||||
return mLauncher.startActivitySafely(v,
|
||||
PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null);
|
||||
PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null,
|
||||
AppLaunchTracker.CONTAINER_SEARCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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.launcher3.model;
|
||||
|
||||
import static com.android.launcher3.util.ResourceBasedOverride.Overrides.getObject;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Callback for receiving various app launch events
|
||||
*/
|
||||
public class AppLaunchTracker implements ResourceBasedOverride {
|
||||
|
||||
/**
|
||||
* Derived from LauncherEvent proto.
|
||||
* TODO: Use proper descriptive constants
|
||||
*/
|
||||
public static final String CONTAINER_DEFAULT = Integer.toString(ContainerType.WORKSPACE);
|
||||
public static final String CONTAINER_ALL_APPS = Integer.toString(ContainerType.ALLAPPS);
|
||||
public static final String CONTAINER_PREDICTIONS = Integer.toString(ContainerType.PREDICTION);
|
||||
public static final String CONTAINER_SEARCH = Integer.toString(ContainerType.SEARCHRESULT);
|
||||
|
||||
|
||||
public static final MainThreadInitializedObject<AppLaunchTracker> INSTANCE =
|
||||
new MainThreadInitializedObject<>(c ->
|
||||
getObject(AppLaunchTracker.class, c, R.string.app_launch_tracker_class));
|
||||
|
||||
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
|
||||
@Nullable String container) { }
|
||||
|
||||
public void onStartApp(ComponentName componentName, UserHandle user,
|
||||
@Nullable String container) { }
|
||||
|
||||
public void onReturnedToHome() { }
|
||||
}
|
|
@ -195,7 +195,7 @@ public abstract class SystemShortcut<T extends BaseDraggingActivity> extends Ite
|
|||
return view -> {
|
||||
Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
|
||||
itemInfo.getTargetComponent().getPackageName());
|
||||
activity.startActivitySafely(view, intent, itemInfo);
|
||||
activity.startActivitySafely(view, intent, itemInfo, null);
|
||||
AbstractFloatingView.closeAllOpenViews(activity);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
|
|||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
|
||||
import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET;
|
||||
import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET;
|
||||
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS;
|
||||
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_DEFAULT;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Intent;
|
||||
|
@ -48,6 +50,8 @@ import com.android.launcher3.util.PackageManagerHelper;
|
|||
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||
import com.android.launcher3.widget.WidgetAddFlowHandler;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Class for handling clicks on workspace and all-apps items
|
||||
*/
|
||||
|
@ -56,9 +60,13 @@ public class ItemClickHandler {
|
|||
/**
|
||||
* Instance used for click handling on items
|
||||
*/
|
||||
public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
|
||||
public static final OnClickListener INSTANCE = getInstance(null);
|
||||
|
||||
private static void onClick(View v) {
|
||||
public static final OnClickListener getInstance(String sourceContainer) {
|
||||
return v -> onClick(v, sourceContainer);
|
||||
}
|
||||
|
||||
private static void onClick(View v, String sourceContainer) {
|
||||
// Make sure that rogue clicks don't get through while allapps is launching, or after the
|
||||
// view has detached (it's possible for this to happen if the view is removed mid touch).
|
||||
if (v.getWindowToken() == null) {
|
||||
|
@ -72,13 +80,14 @@ public class ItemClickHandler {
|
|||
|
||||
Object tag = v.getTag();
|
||||
if (tag instanceof ShortcutInfo) {
|
||||
onClickAppShortcut(v, (ShortcutInfo) tag, launcher);
|
||||
onClickAppShortcut(v, (ShortcutInfo) tag, launcher, sourceContainer);
|
||||
} else if (tag instanceof FolderInfo) {
|
||||
if (v instanceof FolderIcon) {
|
||||
onClickFolderIcon(v);
|
||||
}
|
||||
} else if (tag instanceof AppInfo) {
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
|
||||
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
|
||||
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
|
||||
} else if (tag instanceof LauncherAppWidgetInfo) {
|
||||
if (v instanceof PendingAppWidgetHostView) {
|
||||
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
|
||||
|
@ -154,7 +163,7 @@ public class ItemClickHandler {
|
|||
private static void startMarketIntentForPackage(View v, Launcher launcher, String packageName) {
|
||||
ItemInfo item = (ItemInfo) v.getTag();
|
||||
Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName);
|
||||
launcher.startActivitySafely(v, intent, item);
|
||||
launcher.startActivitySafely(v, intent, item, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,7 +171,8 @@ public class ItemClickHandler {
|
|||
*
|
||||
* @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
|
||||
*/
|
||||
public static void onClickAppShortcut(View v, ShortcutInfo shortcut, Launcher launcher) {
|
||||
public static void onClickAppShortcut(View v, ShortcutInfo shortcut, Launcher launcher,
|
||||
@Nullable String sourceContainer) {
|
||||
if (shortcut.isDisabled()) {
|
||||
final int disabledFlags = shortcut.runtimeStatusFlags & ShortcutInfo.FLAG_DISABLED_MASK;
|
||||
if ((disabledFlags &
|
||||
|
@ -201,10 +211,11 @@ public class ItemClickHandler {
|
|||
}
|
||||
|
||||
// Start activities
|
||||
startAppShortcutOrInfoActivity(v, shortcut, launcher);
|
||||
startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer);
|
||||
}
|
||||
|
||||
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
|
||||
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
|
||||
@Nullable String sourceContainer) {
|
||||
Intent intent;
|
||||
if (item instanceof PromiseAppInfo) {
|
||||
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
|
||||
|
@ -227,6 +238,6 @@ public class ItemClickHandler {
|
|||
intent.setPackage(null);
|
||||
}
|
||||
}
|
||||
launcher.startActivitySafely(v, intent, item);
|
||||
launcher.startActivitySafely(v, intent, item, sourceContainer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ public class OptionsPopupView extends ArrowPopup
|
|||
if (!TextUtils.isEmpty(pickerPackage)) {
|
||||
intent.setPackage(pickerPackage);
|
||||
}
|
||||
return launcher.startActivitySafely(v, intent, null);
|
||||
return launcher.startActivitySafely(v, intent, null, null);
|
||||
}
|
||||
|
||||
public static class OptionItem {
|
||||
|
|
Loading…
Reference in New Issue