2017-03-08 14:25:09 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2008 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;
|
|
|
|
|
|
2019-12-09 14:55:56 -08:00
|
|
|
import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle;
|
2019-09-20 12:51:37 -07:00
|
|
|
|
2017-04-10 10:49:01 -07:00
|
|
|
import android.annotation.TargetApi;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.content.BroadcastReceiver;
|
2019-08-19 13:32:09 -07:00
|
|
|
import android.content.ComponentName;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
2017-03-24 09:07:05 -07:00
|
|
|
import android.content.SharedPreferences;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.content.pm.LauncherActivityInfo;
|
2019-10-02 16:13:34 -07:00
|
|
|
import android.content.pm.LauncherApps;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.content.pm.PackageInstaller;
|
|
|
|
|
import android.content.pm.PackageInstaller.SessionInfo;
|
2017-04-10 10:49:01 -07:00
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
|
import android.content.pm.ResolveInfo;
|
|
|
|
|
import android.database.Cursor;
|
2019-08-19 13:32:09 -07:00
|
|
|
import android.graphics.Bitmap;
|
2017-04-10 10:49:01 -07:00
|
|
|
import android.net.Uri;
|
|
|
|
|
import android.os.AsyncTask;
|
|
|
|
|
import android.os.Build;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.os.UserHandle;
|
2017-04-10 10:49:01 -07:00
|
|
|
import android.provider.Settings;
|
2017-03-08 14:25:09 -08:00
|
|
|
import android.text.TextUtils;
|
2017-03-24 09:07:05 -07:00
|
|
|
import android.util.Log;
|
2017-03-08 14:25:09 -08:00
|
|
|
|
2019-12-09 14:55:56 -08:00
|
|
|
import com.android.launcher3.pm.InstallSessionHelper;
|
2019-08-15 14:53:41 -07:00
|
|
|
import com.android.launcher3.util.Executors;
|
2017-03-08 14:25:09 -08:00
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* BroadcastReceiver to handle session commit intent.
|
|
|
|
|
*/
|
2017-04-10 10:49:01 -07:00
|
|
|
@TargetApi(Build.VERSION_CODES.O)
|
2017-03-08 14:25:09 -08:00
|
|
|
public class SessionCommitReceiver extends BroadcastReceiver {
|
|
|
|
|
|
2017-04-10 10:49:01 -07:00
|
|
|
private static final String TAG = "SessionCommitReceiver";
|
|
|
|
|
|
|
|
|
|
// The content provider for the add to home screen setting. It should be of the format:
|
|
|
|
|
// <package name>.addtohomescreen
|
|
|
|
|
private static final String MARKER_PROVIDER_PREFIX = ".addtohomescreen";
|
2017-03-24 09:07:05 -07:00
|
|
|
|
2017-03-08 14:25:09 -08:00
|
|
|
// Preference key for automatically adding icon to homescreen.
|
|
|
|
|
public static final String ADD_ICON_PREFERENCE_KEY = "pref_add_icon_to_home";
|
2017-04-10 10:49:01 -07:00
|
|
|
public static final String ADD_ICON_PREFERENCE_INITIALIZED_KEY =
|
|
|
|
|
"pref_add_icon_to_home_initialized";
|
2017-03-24 09:07:05 -07:00
|
|
|
|
2017-03-08 14:25:09 -08:00
|
|
|
@Override
|
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2017-09-11 11:18:03 -07:00
|
|
|
if (!isEnabled(context) || !Utilities.ATLEAST_OREO) {
|
2017-03-08 14:25:09 -08:00
|
|
|
// User has decided to not add icons on homescreen.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
|
|
|
|
|
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
|
2019-11-08 13:02:52 -08:00
|
|
|
if (!PackageInstaller.ACTION_SESSION_COMMITTED.equals(intent.getAction())
|
|
|
|
|
|| info == null || user == null) {
|
|
|
|
|
// Invalid intent.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-04-10 10:49:01 -07:00
|
|
|
|
2019-12-09 14:55:56 -08:00
|
|
|
InstallSessionHelper packageInstallerCompat = InstallSessionHelper.INSTANCE.get(context);
|
2019-12-10 14:56:34 -08:00
|
|
|
packageInstallerCompat.restoreDbIfApplicable(info);
|
2019-08-19 13:32:09 -07:00
|
|
|
if (TextUtils.isEmpty(info.getAppPackageName())
|
|
|
|
|
|| info.getInstallReason() != PackageManager.INSTALL_REASON_USER
|
|
|
|
|
|| packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
|
|
|
|
|
packageInstallerCompat.removePromiseIconId(info.getSessionId());
|
2018-02-27 15:06:12 +00:00
|
|
|
return;
|
2017-03-08 14:25:09 -08:00
|
|
|
}
|
|
|
|
|
|
2017-05-04 16:47:11 -07:00
|
|
|
queueAppIconAddition(context, info.getAppPackageName(), user);
|
|
|
|
|
}
|
2017-03-08 14:25:09 -08:00
|
|
|
|
2019-08-19 13:32:09 -07:00
|
|
|
public static void queuePromiseAppIconAddition(Context context, SessionInfo sessionInfo) {
|
|
|
|
|
String packageName = sessionInfo.getAppPackageName();
|
2019-10-02 16:13:34 -07:00
|
|
|
if (context.getSystemService(LauncherApps.class)
|
|
|
|
|
.getActivityList(packageName, getUserHandle(sessionInfo)).isEmpty()) {
|
2019-08-19 13:32:09 -07:00
|
|
|
// Ensure application isn't already installed.
|
|
|
|
|
queueAppIconAddition(context, packageName, sessionInfo.getAppLabel(),
|
|
|
|
|
sessionInfo.getAppIcon(), getUserHandle(sessionInfo));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-04 16:47:11 -07:00
|
|
|
public static void queueAppIconAddition(Context context, String packageName, UserHandle user) {
|
2019-10-02 16:13:34 -07:00
|
|
|
List<LauncherActivityInfo> activities = context.getSystemService(LauncherApps.class)
|
2017-05-04 16:47:11 -07:00
|
|
|
.getActivityList(packageName, user);
|
2019-10-02 16:13:34 -07:00
|
|
|
if (activities.isEmpty()) {
|
2017-03-08 14:25:09 -08:00
|
|
|
// no activity found
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-08-19 13:32:09 -07:00
|
|
|
queueAppIconAddition(context, packageName, activities.get(0).getLabel(), null, user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void queueAppIconAddition(Context context, String packageName,
|
|
|
|
|
CharSequence label, Bitmap icon, UserHandle user) {
|
|
|
|
|
Intent data = new Intent();
|
|
|
|
|
data.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent().setComponent(
|
|
|
|
|
new ComponentName(packageName, "")).setPackage(packageName));
|
|
|
|
|
data.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
|
|
|
|
|
data.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
|
|
|
|
|
|
|
|
|
|
InstallShortcutReceiver.queueApplication(data, user, context);
|
2017-03-08 14:25:09 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static boolean isEnabled(Context context) {
|
|
|
|
|
return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true);
|
|
|
|
|
}
|
2017-04-10 10:49:01 -07:00
|
|
|
|
|
|
|
|
public static void applyDefaultUserPrefs(final Context context) {
|
2017-09-11 11:18:03 -07:00
|
|
|
if (!Utilities.ATLEAST_OREO) {
|
2017-04-10 10:49:01 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SharedPreferences prefs = Utilities.getPrefs(context);
|
|
|
|
|
if (prefs.getAll().isEmpty()) {
|
|
|
|
|
// This logic assumes that the code is the first thing that is executed (before any
|
|
|
|
|
// shared preference is written).
|
|
|
|
|
// TODO: Move this logic to DB upgrade once we have proper support for db downgrade
|
|
|
|
|
// If it is a fresh start, just apply the default value. We use prefs.isEmpty() to infer
|
|
|
|
|
// a fresh start as put preferences always contain some values corresponding to current
|
|
|
|
|
// grid.
|
|
|
|
|
prefs.edit().putBoolean(ADD_ICON_PREFERENCE_KEY, true).apply();
|
|
|
|
|
} else if (!prefs.contains(ADD_ICON_PREFERENCE_INITIALIZED_KEY)) {
|
2019-08-15 14:53:41 -07:00
|
|
|
new PrefInitTask(context).executeOnExecutor(Executors.THREAD_POOL_EXECUTOR);
|
2017-04-10 10:49:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static class PrefInitTask extends AsyncTask<Void, Void, Void> {
|
|
|
|
|
private final Context mContext;
|
|
|
|
|
|
|
|
|
|
PrefInitTask(Context context) {
|
|
|
|
|
mContext = context;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected Void doInBackground(Void... voids) {
|
|
|
|
|
boolean addIconToHomeScreenEnabled = readValueFromMarketApp();
|
|
|
|
|
Utilities.getPrefs(mContext).edit()
|
|
|
|
|
.putBoolean(ADD_ICON_PREFERENCE_KEY, addIconToHomeScreenEnabled)
|
|
|
|
|
.putBoolean(ADD_ICON_PREFERENCE_INITIALIZED_KEY, true)
|
|
|
|
|
.apply();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean readValueFromMarketApp() {
|
|
|
|
|
// Get the marget package
|
|
|
|
|
ResolveInfo ri = mContext.getPackageManager().resolveActivity(
|
|
|
|
|
new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET),
|
|
|
|
|
PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY);
|
|
|
|
|
if (ri == null) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Cursor c = null;
|
|
|
|
|
try {
|
|
|
|
|
c = mContext.getContentResolver().query(
|
|
|
|
|
Uri.parse("content://" + ri.activityInfo.packageName
|
|
|
|
|
+ MARKER_PROVIDER_PREFIX),
|
|
|
|
|
null, null, null, null);
|
|
|
|
|
if (c.moveToNext()) {
|
|
|
|
|
return c.getInt(c.getColumnIndexOrThrow(Settings.NameValueTable.VALUE)) != 0;
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
Log.d(TAG, "Error reading add to homescreen preference", e);
|
|
|
|
|
} finally {
|
|
|
|
|
if (c != null) {
|
|
|
|
|
c.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-08 14:25:09 -08:00
|
|
|
}
|