/** Build any timestamp and label into a single string. */
  public CharSequence getTimestampLabel(Context context) {
    final PackageManager pm = context.getPackageManager();

    // Use local package for resources when none requested
    if (mResPackage == null) mResPackage = context.getPackageName();

    final boolean validTimestamp = mTimestamp > 0;
    final boolean validLabel = mResPackage != null && mLabelRes != -1;

    final CharSequence timeClause =
        validTimestamp
            ? DateUtils.getRelativeTimeSpanString(
                mTimestamp,
                System.currentTimeMillis(),
                DateUtils.MINUTE_IN_MILLIS,
                DateUtils.FORMAT_ABBREV_RELATIVE)
            : null;
    final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes, null) : null;

    if (validTimestamp && validLabel) {
      return context.getString(
          com.android.internal.R.string.contact_status_update_attribution_with_date,
          timeClause,
          labelClause);
    } else if (validLabel) {
      return context.getString(
          com.android.internal.R.string.contact_status_update_attribution, labelClause);
    } else if (validTimestamp) {
      return timeClause;
    } else {
      return null;
    }
  }
  /** Build {@link UidDetail} object, blocking until all {@link Drawable} lookup is finished. */
  private UidDetail buildUidDetail(int uid) {
    final Resources res = mContext.getResources();
    final PackageManager pm = mContext.getPackageManager();

    final UidDetail detail = new UidDetail();
    detail.label = pm.getNameForUid(uid);
    detail.icon = pm.getDefaultActivityIcon();

    // handle special case labels
    switch (uid) {
      case android.os.Process.SYSTEM_UID:
        detail.label = res.getString(R.string.process_kernel_label);
        detail.icon = pm.getDefaultActivityIcon();
        return detail;
      case TrafficStats.UID_REMOVED:
        detail.label = res.getString(R.string.data_usage_uninstalled_apps);
        detail.icon = pm.getDefaultActivityIcon();
        return detail;
      case TrafficStats.UID_TETHERING:
        final ConnectivityManager cm =
            (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        detail.label = res.getString(Utils.getTetheringLabel(cm));
        detail.icon = pm.getDefaultActivityIcon();
        return detail;
    }

    // otherwise fall back to using packagemanager labels
    final String[] packageNames = pm.getPackagesForUid(uid);
    final int length = packageNames != null ? packageNames.length : 0;

    try {
      if (length == 1) {
        final ApplicationInfo info = pm.getApplicationInfo(packageNames[0], 0);
        detail.label = info.loadLabel(pm).toString();
        detail.icon = info.loadIcon(pm);
      } else if (length > 1) {
        detail.detailLabels = new CharSequence[length];
        for (int i = 0; i < length; i++) {
          final String packageName = packageNames[i];
          final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
          final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);

          detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
          if (packageInfo.sharedUserLabel != 0) {
            detail.label =
                pm.getText(packageName, packageInfo.sharedUserLabel, packageInfo.applicationInfo)
                    .toString();
            detail.icon = appInfo.loadIcon(pm);
          }
        }
      }
    } catch (NameNotFoundException e) {
    }

    if (TextUtils.isEmpty(detail.label)) {
      detail.label = Integer.toString(uid);
    }

    return detail;
  }
    void ensureLabel(PackageManager pm) {
      if (mLabel != null) {
        return;
      }

      try {
        ApplicationInfo ai = pm.getApplicationInfo(mProcessName, 0);
        if (ai.uid == mUid) {
          mDisplayLabel = ai.loadLabel(pm);
          mLabel = mDisplayLabel.toString();
          mPackageInfo = ai;
          return;
        }
      } catch (PackageManager.NameNotFoundException e) {
      }

      // If we couldn't get information about the overall
      // process, try to find something about the uid.
      String[] pkgs = pm.getPackagesForUid(mUid);

      // If there is one package with this uid, that is what we want.
      if (pkgs.length == 1) {
        try {
          ApplicationInfo ai = pm.getApplicationInfo(pkgs[0], 0);
          mDisplayLabel = ai.loadLabel(pm);
          mLabel = mDisplayLabel.toString();
          mPackageInfo = ai;
          return;
        } catch (PackageManager.NameNotFoundException e) {
        }
      }

      // If there are multiple, see if one gives us the official name
      // for this uid.
      for (String name : pkgs) {
        try {
          PackageInfo pi = pm.getPackageInfo(name, 0);
          if (pi.sharedUserLabel != 0) {
            CharSequence nm = pm.getText(name, pi.sharedUserLabel, pi.applicationInfo);
            if (nm != null) {
              mDisplayLabel = nm;
              mLabel = nm.toString();
              mPackageInfo = pi.applicationInfo;
              return;
            }
          }
        } catch (PackageManager.NameNotFoundException e) {
        }
      }

      // If still don't have anything to display, just use the
      // service info.
      if (mServices.size() > 0) {
        mPackageInfo = mServices.values().iterator().next().mServiceInfo.applicationInfo;
        mDisplayLabel = mPackageInfo.loadLabel(pm);
        mLabel = mDisplayLabel.toString();
        return;
      }

      // Finally... whatever, just pick the first package's name.
      try {
        ApplicationInfo ai = pm.getApplicationInfo(pkgs[0], 0);
        mDisplayLabel = ai.loadLabel(pm);
        mLabel = mDisplayLabel.toString();
        mPackageInfo = ai;
        return;
      } catch (PackageManager.NameNotFoundException e) {
      }
    }