Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f599ccfe authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Showing icons for apps on sdcard which are not available during system boot.

issue 15852084

Change-Id: I1e6f59a413581ae3af4219ab32cb5af3d726d382
parent bb474f6d
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@
    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
    <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
    <uses-permission android:name="com.android.launcher3.permission.READ_SETTINGS" />
@@ -206,6 +208,12 @@
            </intent-filter>
        </receiver>

        <receiver android:name="com.android.launcher3.StartupReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <!-- The settings provider contains Home's data, like the workspace favorites -->
        <provider
            android:name="com.android.launcher3.LauncherProvider"
+97 −28
Original line number Diff line number Diff line
@@ -19,12 +19,19 @@ package com.android.launcher3;
import android.app.SearchManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.*;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
@@ -45,11 +52,11 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;
import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData;

import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
@@ -63,6 +70,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -157,6 +165,9 @@ public class LauncherModel extends BroadcastReceiver
    // sBgWorkspaceScreens is the ordered set of workspace screens.
    static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();

    // sPendingPackages is a set of packages which could be on sdcard and are not available yet
    static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages = new HashMap<>();

    // </ only access in worker thread >

    private IconCache mIconCache;
@@ -1826,6 +1837,9 @@ public class LauncherModel extends BroadcastReceiver
            final PackageManager manager = context.getPackageManager();
            final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
            final boolean isSafeMode = manager.isSafeMode();
            final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
            final boolean isSdCardReady = context.registerReceiver(null,
                    new IntentFilter(StartupReceiver.SYESTEM_READY)) != null;

            LauncherAppState app = LauncherAppState.getInstance();
            DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -1919,6 +1933,7 @@ public class LauncherModel extends BroadcastReceiver
                        try {
                            int itemType = c.getInt(itemTypeIndex);
                            boolean restored = 0 != c.getInt(restoredIndex);
                            boolean allowMissingTarget = false;

                            switch (itemType) {
                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
@@ -1935,30 +1950,51 @@ public class LauncherModel extends BroadcastReceiver
                                try {
                                    intent = Intent.parseUri(intentDescription, 0);
                                    ComponentName cn = intent.getComponent();
                                    if (cn != null && !isValidPackageActivity(context, cn, user)) {
                                    if (cn != null && cn.getPackageName() != null) {
                                        boolean validPkg = launcherApps.isPackageEnabledForProfile(
                                                cn.getPackageName(), user);
                                        boolean validComponent = validPkg &&
                                                launcherApps.isActivityEnabledForProfile(cn, user);

                                        if (validComponent) {
                                            if (restored) {
                                            // might be installed later
                                                // no special handling necessary for this item
                                                restoredRows.add(id);
                                                restored = false;
                                            }
                                        } else if (validPkg) {
                                            // The app is installed but the component is no
                                            // longer available.
                                            Launcher.addDumpLog(TAG,
                                                    "Invalid component removed: " + cn, true);
                                            itemsToRemove.add(id);
                                            continue;
                                        } else if (restored) {
                                            // Package is not yet available but might be
                                            // installed later.
                                            Launcher.addDumpLog(TAG,
                                                    "package not yet restored: " + cn, true);
                                        } else {
                                            if (!mAppsCanBeOnRemoveableStorage) {
                                        } else if (isSdCardReady) {
                                            // Do not wait for external media load anymore.
                                            // Log the invalid package, and remove it
                                            Launcher.addDumpLog(TAG,
                                                    "Invalid package removed: " + cn, true);
                                            itemsToRemove.add(id);
                                            continue;
                                        } else {
                                                // If apps can be on external storage, then we just
                                                // leave them for the user to remove (maybe add
                                                // visual treatment to it)
                                                Launcher.addDumpLog(TAG,
                                                        "Invalid package found: " + cn, true);
                                            // SdCard is not ready yet. Package might get available,
                                            // once it is ready.
                                            Launcher.addDumpLog(TAG, "Invalid package: " + cn
                                                    + " (check again later)", true);
                                            HashSet<String> pkgs = sPendingPackages.get(user);
                                            if (pkgs == null) {
                                                pkgs = new HashSet<>();
                                                sPendingPackages.put(user, pkgs);
                                            }
                                            continue;
                                            pkgs.add(cn.getPackageName());
                                            allowMissingTarget = true;
                                            // Add the icon on the workspace anyway.
                                        }
                                    } else if (restored) {
                                        // no special handling necessary for this restored item
                                        restoredRows.add(id);
                                        restored = false;
                                    }
                                } catch (URISyntaxException e) {
                                    Launcher.addDumpLog(TAG,
@@ -1980,8 +2016,8 @@ public class LauncherModel extends BroadcastReceiver
                                    }
                                } else if (itemType ==
                                        LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                                    info = getShortcutInfo(manager, intent, user, context, c, iconIndex,
                                            titleIndex, mLabelCache);
                                    info = getShortcutInfo(manager, intent, user, context, c,
                                            iconIndex, titleIndex, mLabelCache, allowMissingTarget);
                                } else {
                                    info = getShortcutInfo(c, context, iconTypeIndex,
                                            iconPackageIndex, iconResourceIndex, iconIndex,
@@ -2198,6 +2234,12 @@ public class LauncherModel extends BroadcastReceiver
                    }
                }

                if (!isSdCardReady && !sPendingPackages.isEmpty()) {
                    context.registerReceiver(new AppsAvailabilityCheck(),
                            new IntentFilter(StartupReceiver.SYESTEM_READY),
                            null, sWorker);
                }

                if (loadedOldDb) {
                    long maxScreenId = 0;
                    // If we're importing we use the old screen order.
@@ -2743,6 +2785,33 @@ public class LauncherModel extends BroadcastReceiver
        sWorker.post(task);
    }

    private class AppsAvailabilityCheck extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            synchronized (sBgLock) {
                final LauncherAppsCompat launcherApps = LauncherAppsCompat
                        .getInstance(mApp.getContext());
                ArrayList<String> packagesRemoved;
                for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {
                    UserHandleCompat user = entry.getKey();
                    packagesRemoved = new ArrayList<>();
                    for (String pkg : entry.getValue()) {
                        if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
                            Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
                            packagesRemoved.add(pkg);
                        }
                    }
                    if (!packagesRemoved.isEmpty()) {
                        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,
                                packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
                    }
                }
            sPendingPackages.clear();
            }
        }
    }

    private class PackageUpdatedTask implements Runnable {
        int mOp;
        String[] mPackages;
@@ -3006,7 +3075,7 @@ public class LauncherModel extends BroadcastReceiver
     */
    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
            UserHandleCompat user, Context context) {
        return getShortcutInfo(manager, intent, user, context, null, -1, -1, null);
        return getShortcutInfo(manager, intent, user, context, null, -1, -1, null, false);
    }

    /**
@@ -3016,7 +3085,7 @@ public class LauncherModel extends BroadcastReceiver
     */
    public ShortcutInfo getShortcutInfo(PackageManager manager, Intent intent,
            UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
            HashMap<Object, CharSequence> labelCache) {
            HashMap<Object, CharSequence> labelCache, boolean allowMissingTarget) {
        if (user == null) {
            Log.d(TAG, "Null user found in getShortcutInfo");
            return null;
@@ -3032,7 +3101,7 @@ public class LauncherModel extends BroadcastReceiver
        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        newIntent.setComponent(componentName);
        LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);
        if (lai == null) {
        if ((lai == null) && !allowMissingTarget) {
            Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);
            return null;
        }
+15 −0
Original line number Diff line number Diff line
package com.android.launcher3;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartupReceiver extends BroadcastReceiver {

    static final String SYESTEM_READY = "com.android.launcher3.SYESTEM_READY";

    @Override
    public void onReceive(Context context, Intent intent) {
        context.sendStickyBroadcast(new Intent(SYESTEM_READY));
    }
}