boolean updateSize(Context context, Debug.MemoryInfo mem, int curSeq) {
   mSize = ((long) mem.getTotalPss()) * 1024;
   if (mCurSeq == curSeq) {
     String sizeStr = Formatter.formatShortFileSize(context, mSize);
     if (!sizeStr.equals(mSizeStr)) {
       mSizeStr = sizeStr;
       // We update this on the second tick where we update just
       // the text in the current items, so no need to say we
       // changed here.
       return false;
     }
   }
   return false;
 }
  /**
   * Get all running apps 如何判断多个进程是属于一个app? 1. 相同的前缀包名 返回的运行时应用列表, 按照内存占用量降序排序
   *
   * @param ctx
   * @return
   */
  public List<Map<String, Object>> getRunningApps(Context ctx) {

    // get all running app processes
    List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
    if (runningAppProcesses == null) return null;

    // sort all running app processes
    Collections.sort(
        runningAppProcesses,
        new Comparator<RunningAppProcessInfo>() {
          @Override
          public int compare(RunningAppProcessInfo lhs, RunningAppProcessInfo rhs) {
            String lhsPkgName = lhs.processName.split(":")[0];
            String rhsPkgName = rhs.processName.split(":")[0];
            return lhsPkgName.compareToIgnoreCase(rhsPkgName);
          }
        });

    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    ResolveInfo resolveInfo =
        appHelper.getPm().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
    String currentHomePackage = resolveInfo.activityInfo.packageName;
    IGNORE_PKGS.add(currentHomePackage);

    // remove all ignored packages
    Log.i(TAG, "before remove :" + runningAppProcesses.size());
    ArrayList<RunningAppProcessInfo> toBeRemoved = new ArrayList<RunningAppProcessInfo>();
    for (RunningAppProcessInfo runningProcessInfo : runningAppProcesses) {
      Log.i(TAG, "after sort:" + runningProcessInfo.processName);
      try {
        String appPkgname = runningProcessInfo.processName.split(":")[0];
        if (IGNORE_PKGS.contains(appPkgname)) {
          toBeRemoved.add(runningProcessInfo);
        }
      } catch (Exception e) {
        e.printStackTrace();
        Log.w(TAG, "exception raised while remove ignore list:" + e.toString());
      }
    }
    runningAppProcesses.removeAll(toBeRemoved);
    Log.i(
        TAG,
        "removed :"
            + toBeRemoved.size()
            + " ignored packages, after remove size:"
            + runningAppProcesses.size());

    Map<String, Map<String, Object>> runningApps = new HashMap<String, Map<String, Object>>();
    // iterate the running app process list
    for (RunningAppProcessInfo runningProcessInfo : runningAppProcesses) {
      String[] pkgNameSections = runningProcessInfo.processName.split(":");
      Log.i(
          TAG,
          "process name:"
              + runningProcessInfo.processName
              + ", pkgNameSections length:"
              + pkgNameSections.length);
      if (pkgNameSections.length == 0) {
        // TODO: process name is ""?
        continue;
      }
      String appPkgname = pkgNameSections[0];
      String subProcessName = (pkgNameSections.length == 2) ? pkgNameSections[1] : null;
      Log.i(TAG, "appPkgname:" + appPkgname + ", subProcessName:" + subProcessName);

      // get application info from package name
      ApplicationInfo appInfo = appHelper.getApplicationInfo(appPkgname);
      if (appInfo == null) appInfo = appHelper.getApplicationInfo(runningProcessInfo.processName);

      // get app info by app package name
      Map<String, Object> appInfoMap = runningApps.get(appPkgname);
      if (appInfoMap == null) appInfoMap = new HashMap<String, Object>();

      // put app package name
      if (!appInfoMap.containsKey(PKG_NAME)) {
        appInfoMap.put(PKG_NAME, appPkgname);
      }

      // put app uid
      if (!appInfoMap.containsKey(APP_UID)) {
        appInfoMap.put(APP_UID, runningProcessInfo.uid);
      }

      // put recommend flag
      if (!appInfoMap.containsKey(APP_RECOMMEND_CLEAN)) {
        appInfoMap.put(APP_RECOMMEND_CLEAN, !NOT_RECOMMAND_PKGS.contains(appPkgname));
      }

      // only main process can get human readable name
      if (appInfo != null) {
        appInfoMap.put(APP_NAME, appInfo.loadLabel(appHelper.getPm()).toString());
      } else if (!appInfoMap.containsKey(APP_NAME)) {
        appInfoMap.put(APP_NAME, appPkgname);
      }

      // get and put app icon
      if (appInfo != null) {
        appInfoMap.put(APP_ICON, appInfo.loadIcon(appHelper.getPm()));
      } else if (!appInfoMap.containsKey(APP_ICON)) {
        appInfoMap.put(APP_ICON, android.R.drawable.sym_def_app_icon);
      }

      // get memory size of app process, store mem info <Key(pid), Value(Debug.MemoryInfo)>
      SparseArray<Debug.MemoryInfo> memoryInfoArray =
          (SparseArray<Debug.MemoryInfo>) appInfoMap.get(APP_PROC_MEM);
      if (memoryInfoArray == null) memoryInfoArray = new SparseArray<Debug.MemoryInfo>();
      Debug.MemoryInfo memInfo = getDebugMemoryInfos(new int[] {runningProcessInfo.pid})[0];
      memoryInfoArray.put(runningProcessInfo.pid, memInfo);
      appInfoMap.put(APP_PROC_MEM, memoryInfoArray);

      // update total
      int totalPss = 0;
      if (appInfoMap.containsKey(APP_TOTAL_PSS)) totalPss = (Integer) appInfoMap.get(APP_TOTAL_PSS);
      totalPss += memInfo.getTotalPss();
      appInfoMap.put(APP_TOTAL_PSS, totalPss);

      // add process in process array
      List<RunningAppProcessInfo> processes =
          (ArrayList<RunningAppProcessInfo>) appInfoMap.get(APP_PROCS);
      if (processes == null) processes = new ArrayList<RunningAppProcessInfo>();
      processes.add(runningProcessInfo);
      appInfoMap.put(APP_PROCS, processes);

      runningApps.put(appPkgname, appInfoMap);
    }
    return sortMap(runningApps);
  }
  @Override
  protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);

    if (mDragging) {
      if (mAnimationState == ANIMATION_STATE_STARTING) {
        mAnimationStartTime = SystemClock.uptimeMillis();
        mAnimationState = ANIMATION_STATE_RUNNING;
      }

      if (mAnimationState == ANIMATION_STATE_RUNNING) {
        float normalized =
            (float) (SystemClock.uptimeMillis() - mAnimationStartTime) / mAnimationDuration;
        if (normalized >= 1.0f) {
          mAnimationState = ANIMATION_STATE_DONE;
        }
        normalized = Math.min(normalized, 1.0f);
        final float value = mAnimationFrom + (mAnimationTo - mAnimationFrom) * normalized;

        switch (mAnimationType) {
          case ANIMATION_TYPE_SCALE:
            if (mDrawModeBitmap && mDragBitmap != null) {
              final Bitmap dragBitmap = mDragBitmap;
              canvas.save();
              canvas.translate(
                  getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
                  getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY);
              canvas.translate(
                  (dragBitmap.getWidth() * (1.0f - value)) / 2,
                  (dragBitmap.getHeight() * (1.0f - value)) / 2);
              canvas.scale(value, value);
              canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint);
              canvas.restore();
            } else {
              canvas.save();
              canvas.translate(
                  getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
                  getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY);
              canvas.translate(
                  (mDrawWidth * (1.0f - value)) / 2, (mDrawHeight * (1.0f - value)) / 2);
              canvas.drawRoundRect(
                  new RectF(0, 0, mDrawWidth, mDrawHeight), 8.0f, 8.0f, mRectPaint);
              canvas.restore();
            }
            break;
        }
      } else {
        // Draw actual icon being dragged
        if (mDrawModeBitmap && mDragBitmap != null) {
          canvas.drawBitmap(
              mDragBitmap,
              getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
              getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY,
              mDragPaint);
        } else {
          canvas.save();
          canvas.translate(
              getScrollX() + mLastMotionX - mTouchOffsetX - mBitmapOffsetX,
              getScrollY() + mLastMotionY - mTouchOffsetY - mBitmapOffsetY);
          canvas.drawRoundRect(new RectF(0, 0, mDrawWidth, mDrawHeight), 8.0f, 8.0f, mRectPaint);
          canvas.restore();
        }
      }
    }
    if (pids.length > 0 && AlmostNexusSettingsHelper.getDebugShowMemUsage(getContext())) {
      mRectPaint.setTextSize(debugTextSize);
      mRectPaint.setAntiAlias(true);
      mRectPaint.setColor(0xff000000);
      if (pids.length > 0) canvas.drawRect(0, 0, getWidth(), 70, mRectPaint);
      mRectPaint.setColor(0xffffffff);
      memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
      for (Debug.MemoryInfo pidMemoryInfo : memoryInfoArray) {
        canvas.drawText(
            "getTotalPrivateDirty: " + pidMemoryInfo.getTotalPrivateDirty(),
            0,
            debugTextSize,
            mRectPaint);
        canvas.drawText(
            "getTotalPss: " + pidMemoryInfo.getTotalPss(), 0, debugTextSize * 2, mRectPaint);
        canvas.drawText(
            "getTotalSharedDirty: " + pidMemoryInfo.getTotalSharedDirty(),
            0,
            debugTextSize * 3,
            mRectPaint);
      }
    }
  }