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