14179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal/* 24179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * Copyright (C) 2008 The Android Open Source Project 34179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * 44179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License"); 54179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * you may not use this file except in compliance with the License. 64179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * You may obtain a copy of the License at 74179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * 84179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * http://www.apache.org/licenses/LICENSE-2.0 94179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * 104179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * Unless required by applicable law or agreed to in writing, software 114179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS, 124179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * See the License for the specific language governing permissions and 144179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * limitations under the License. 154179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal */ 164179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 174179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalpackage com.android.launcher3; 184179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 193e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.annotation.TargetApi; 204179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.BroadcastReceiver; 214179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.Context; 224179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.Intent; 230d7f19a56649076b08b88fcba83cb81ddacc4242Sunny Goyalimport android.content.SharedPreferences; 244179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.pm.LauncherActivityInfo; 254179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.pm.PackageInstaller; 264179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.content.pm.PackageInstaller.SessionInfo; 273e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.content.pm.PackageManager; 283e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.content.pm.ResolveInfo; 293e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.database.Cursor; 303e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.net.Uri; 313e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.os.AsyncTask; 323e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.os.Build; 334179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.os.Process; 344179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.os.UserHandle; 353e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyalimport android.provider.Settings; 364179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport android.text.TextUtils; 370d7f19a56649076b08b88fcba83cb81ddacc4242Sunny Goyalimport android.util.Log; 384179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 394179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport com.android.launcher3.compat.LauncherAppsCompat; 404179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 414179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalimport java.util.List; 424179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 434179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal/** 444179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal * BroadcastReceiver to handle session commit intent. 454179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal */ 463e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal@TargetApi(Build.VERSION_CODES.O) 474179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyalpublic class SessionCommitReceiver extends BroadcastReceiver { 484179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 493e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal private static final String TAG = "SessionCommitReceiver"; 503e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 513e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // The content provider for the add to home screen setting. It should be of the format: 523e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // <package name>.addtohomescreen 533e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal private static final String MARKER_PROVIDER_PREFIX = ".addtohomescreen"; 540d7f19a56649076b08b88fcba83cb81ddacc4242Sunny Goyal 554179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal // Preference key for automatically adding icon to homescreen. 564179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal public static final String ADD_ICON_PREFERENCE_KEY = "pref_add_icon_to_home"; 573e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal public static final String ADD_ICON_PREFERENCE_INITIALIZED_KEY = 583e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal "pref_add_icon_to_home_initialized"; 590d7f19a56649076b08b88fcba83cb81ddacc4242Sunny Goyal 604179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal @Override 614179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal public void onReceive(Context context, Intent intent) { 62e24cb63b811e2885a69e7df794e9972cdf5a57b9Hyunyoung Song if (!isEnabled(context) || !Utilities.ATLEAST_OREO) { 634179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal // User has decided to not add icons on homescreen. 644179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal return; 654179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal } 664179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 674179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); 684179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER); 693e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 70a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal if (Process.myUserHandle().equals(user)) { 71a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal if (TextUtils.isEmpty(info.getAppPackageName()) || 72a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal info.getInstallReason() != PackageManager.INSTALL_REASON_USER) { 73a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal return; 74a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal } 754179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal } 764179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 77a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal queueAppIconAddition(context, info.getAppPackageName(), user); 78a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal } 794179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 80a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal public static void queueAppIconAddition(Context context, String packageName, UserHandle user) { 814179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(context) 82a474a9bcf5d533ac942c58409e45e5ec6d8b4893Sunny Goyal .getActivityList(packageName, user); 834179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal if (activities == null || activities.isEmpty()) { 844179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal // no activity found 854179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal return; 864179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal } 874179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal InstallShortcutReceiver.queueActivityInfo(activities.get(0), context); 884179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal } 894179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal 904179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal public static boolean isEnabled(Context context) { 914179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal return Utilities.getPrefs(context).getBoolean(ADD_ICON_PREFERENCE_KEY, true); 924179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal } 933e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 943e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal public static void applyDefaultUserPrefs(final Context context) { 95e24cb63b811e2885a69e7df794e9972cdf5a57b9Hyunyoung Song if (!Utilities.ATLEAST_OREO) { 963e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal return; 973e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 983e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal SharedPreferences prefs = Utilities.getPrefs(context); 993e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal if (prefs.getAll().isEmpty()) { 1003e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // This logic assumes that the code is the first thing that is executed (before any 1013e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // shared preference is written). 1023e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // TODO: Move this logic to DB upgrade once we have proper support for db downgrade 1033e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // If it is a fresh start, just apply the default value. We use prefs.isEmpty() to infer 1043e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // a fresh start as put preferences always contain some values corresponding to current 1053e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // grid. 1063e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal prefs.edit().putBoolean(ADD_ICON_PREFERENCE_KEY, true).apply(); 1073e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } else if (!prefs.contains(ADD_ICON_PREFERENCE_INITIALIZED_KEY)) { 1083e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal new PrefInitTask(context).executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR); 1093e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1103e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1113e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 1123e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal private static class PrefInitTask extends AsyncTask<Void, Void, Void> { 1133e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal private final Context mContext; 1143e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 1153e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal PrefInitTask(Context context) { 1163e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal mContext = context; 1173e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1183e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 1193e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal @Override 1203e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal protected Void doInBackground(Void... voids) { 1213e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal boolean addIconToHomeScreenEnabled = readValueFromMarketApp(); 1223e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal Utilities.getPrefs(mContext).edit() 1233e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal .putBoolean(ADD_ICON_PREFERENCE_KEY, addIconToHomeScreenEnabled) 1243e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal .putBoolean(ADD_ICON_PREFERENCE_INITIALIZED_KEY, true) 1253e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal .apply(); 1263e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal return null; 1273e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1283e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 1293e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal public boolean readValueFromMarketApp() { 1303e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal // Get the marget package 1313e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal ResolveInfo ri = mContext.getPackageManager().resolveActivity( 1323e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_APP_MARKET), 1333e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_SYSTEM_ONLY); 1343e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal if (ri == null) { 1353e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal return true; 1363e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1373e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal 1383e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal Cursor c = null; 1393e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal try { 1403e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal c = mContext.getContentResolver().query( 1413e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal Uri.parse("content://" + ri.activityInfo.packageName 1423e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal + MARKER_PROVIDER_PREFIX), 1433e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal null, null, null, null); 1443e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal if (c.moveToNext()) { 1453e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal return c.getInt(c.getColumnIndexOrThrow(Settings.NameValueTable.VALUE)) != 0; 1463e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1473e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } catch (Exception e) { 1483e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal Log.d(TAG, "Error reading add to homescreen preference", e); 1493e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } finally { 1503e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal if (c != null) { 1513e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal c.close(); 1523e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1533e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1543e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal return true; 1553e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1563e443a24576be93c8ecdeba29b04aa07b165d718Sunny Goyal } 1574179e9b88f21d49e24ee005c00b0dad0de0ec343Sunny Goyal} 158