插拔SD卡对SD中的应用桌面快捷方式影响流程分析



该流程主要是在PackageManagerService.java中


首先通过内部类AppDirObserver extends FileObserver监听没一个应用创建的文件夹,在插拔SD卡时的onEvent中调用 

p = scanPackageLI(fullPath, flags,
                                SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
                                System.currentTimeMillis(), UserHandle.ALL);


  private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
            int parseFlags, int scanMode, long currentTime, UserHandle user) {

    .......

    // Request the ActivityManager to kill the process(only for existing packages)
        // so that we do not end up in a confused state while the user is still using the older
        // version of the application while the new one gets installed.
        if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
            // If the package lives in an asec, tell everyone that the container is going
            // away so they can clean up any references to its resources (which would prevent
            // vold from being able to unmount the asec)
            if (isForwardLocked(pkg) || isExternal(pkg)) {
                if (DEBUG_INSTALL) {
                    Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE");
                }
                final int[] uidArray = new int[] { pkg.applicationInfo.uid };
                final ArrayList<String> pkgList = new ArrayList<String>(1);
                pkgList.add(pkg.applicationInfo.packageName);
                sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
            }


            // Post the request that it be killed now that the going-away broadcast is en route
            killApplication(pkg.applicationInfo.packageName,
                        pkg.applicationInfo.uid, "update pkg");

        }

.........

}

   private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing,
           ArrayList<String> pkgList, int uidArr[], IIntentReceiver finishedReceiver) {
        int size = pkgList.size();
        if (size > 0) {
            // Send broadcasts here
            Bundle extras = new Bundle();
            extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList
                    .toArray(new String[size]));
            if (uidArr != null) {
                extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidArr);
            }
            if (replacing && !mediaStatus) {
                extras.putBoolean(Intent.EXTRA_REPLACING, replacing);
            }
            String action = mediaStatus ? Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
                    : Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE;
            sendPackageBroadcast(action, null, extras, null, finishedReceiver, null);
        }
    }


然后发出Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE在LauncherModel.java有接受该Intent

  /**
     * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
     * ACTION_PACKAGE_CHANGED.
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);


        final String action = intent.getAction();


        if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
                || Intent.ACTION_PACKAGE_REMOVED.equals(action)
                || Intent.ACTION_PACKAGE_ADDED.equals(action)) {

......
          }else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
if (!replacing) {
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
enqueuePackageUpdated(new PackageUpdatedTask(
PackageUpdatedTask.OP_UNAVAILABLE, packages));
}
// else, we are replacing the packages, so ignore this event and wait for
// EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time
        } 
        ......
    }

启动PackageUpdatedTask线程


执行

 private class PackageUpdatedTask implements Runnable {

........

if (packageRemoved) {
                        for (String pn : removedPackageNames) {
                            ArrayList<ItemInfo> infos = getItemInfoForPackageName(pn);
                            for (ItemInfo i : infos) {
                                deleteItemFromDatabase(context, i);
                            }
                        }


                        // Remove any queued items from the install queue
                        String spKey = LauncherAppState.getSharedPreferencesKey();
                        SharedPreferences sp =
                                context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
                        InstallShortcutReceiver.removeFromInstallQueue(sp, removedPackageNames)

   ........

}


static void deleteItemFromDatabase(Context context, final ItemInfo item) {

........

case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                            sBgWorkspaceItems.remove(item);
                            break;


........

           sBgItemsIdMap.remove(item.id);

            sBgDbIconCache.remove(item);

........

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值