private String readFile(String file, char endChar) {
    // Permit disk reads here, as /proc/meminfo isn't really "on
    // disk" and should be fast.  TODO: make BlockGuard ignore
    // /proc/ and /sys/ files perhaps?
    StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
    FileInputStream is = null;
    try {
      is = new FileInputStream(file);
      int len = is.read(mBuffer);
      is.close();

      if (len > 0) {
        int i;
        for (i = 0; i < len; i++) {
          if (mBuffer[i] == endChar) {
            break;
          }
        }
        return new String(mBuffer, 0, i);
      }
    } catch (java.io.FileNotFoundException e) {
    } catch (java.io.IOException e) {
    } finally {
      IoUtils.closeQuietly(is);
      StrictMode.setThreadPolicy(savedPolicy);
    }
    return null;
  }
 private static void tryObtainingDataDirLockOrDie() {
   StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
   StrictMode.allowThreadDiskWrites();
   try {
     String dataPath = PathUtils.getDataDirectory(ContextUtils.getApplicationContext());
     File lockFile = new File(dataPath, EXCLUSIVE_LOCK_FILE);
     boolean success = false;
     try {
       // Note that the file is not closed intentionally.
       RandomAccessFile file = new RandomAccessFile(lockFile, "rw");
       sExclusiveFileLock = file.getChannel().tryLock();
       success = sExclusiveFileLock != null;
     } catch (IOException e) {
       Log.w(TAG, "Failed to create lock file " + lockFile, e);
     }
     if (!success) {
       Log.w(
           TAG,
           "The app may have another WebView opened in a separate process. "
               + "This is not recommended and may stop working in future versions.");
     }
   } finally {
     StrictMode.setThreadPolicy(oldPolicy);
   }
 }
Example #3
0
 /**
  * Check the cached value to figure out if the feature is enabled. We have to use the cached value
  * because native library may not yet been loaded.
  *
  * @return Whether the feature is enabled.
  */
 private static boolean isEnabledInPrefs() {
   // Will go away once the feature is enabled for everyone by default.
   StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
   try {
     return ChromePreferenceManager.getInstance(ContextUtils.getApplicationContext())
         .getCachedWebApkRuntimeEnabled();
   } finally {
     StrictMode.setThreadPolicy(oldPolicy);
   }
 }
Example #4
0
  /**
   * Return the amount of physical memory on this device in kilobytes.
   *
   * @return Amount of physical memory in kilobytes, or 0 if there was an error trying to access the
   *     information.
   */
  private static int amountOfPhysicalMemoryKB() {
    // Extract total memory RAM size by parsing /proc/meminfo, note that
    // this is exactly what the implementation of sysconf(_SC_PHYS_PAGES)
    // does. However, it can't be called because this method must be
    // usable before any native code is loaded.

    // An alternative is to use ActivityManager.getMemoryInfo(), but this
    // requires a valid ActivityManager handle, which can only come from
    // a valid Context object, which itself cannot be retrieved
    // during early startup, where this method is called. And making it
    // an explicit parameter here makes all call paths _much_ more
    // complicated.

    Pattern pattern = Pattern.compile("^MemTotal:\\s+([0-9]+) kB$");
    // Synchronously reading files in /proc in the UI thread is safe.
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
    try {
      FileReader fileReader = new FileReader("/proc/meminfo");
      try {
        BufferedReader reader = new BufferedReader(fileReader);
        try {
          String line;
          for (; ; ) {
            line = reader.readLine();
            if (line == null) {
              Log.w(TAG, "/proc/meminfo lacks a MemTotal entry?");
              break;
            }
            Matcher m = pattern.matcher(line);
            if (!m.find()) continue;

            int totalMemoryKB = Integer.parseInt(m.group(1));
            // Sanity check.
            if (totalMemoryKB <= 1024) {
              Log.w(TAG, "Invalid /proc/meminfo total size in kB: " + m.group(1));
              break;
            }

            return totalMemoryKB;
          }

        } finally {
          reader.close();
        }
      } finally {
        fileReader.close();
      }
    } catch (Exception e) {
      Log.w(TAG, "Cannot get total physical size from /proc/meminfo", e);
    } finally {
      StrictMode.setThreadPolicy(oldPolicy);
    }

    return 0;
  }
 /**
  * @see #getMacForUrl
  * @param url The URL to validate.
  * @param mac The bytes of a previously-calculated MAC.
  * @return true if the MAC is a valid MAC for the URL, false otherwise.
  */
 public static boolean isUrlValid(Context context, String url, byte[] mac) {
   byte[] goodMac = null;
   // Temporarily allowing disk access while fixing. TODO: http://crbug.com/525785
   StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
   try {
     long time = SystemClock.elapsedRealtime();
     goodMac = getMacForUrl(context, url);
     LaunchMetrics.recordWebappHistogramTimes(SystemClock.elapsedRealtime() - time);
   } finally {
     StrictMode.setThreadPolicy(oldPolicy);
   }
   if (goodMac == null) {
     return false;
   }
   return constantTimeAreArraysEqual(goodMac, mac);
 }
  /**
   * Performs all prefs migrations in the background thread to avoid StrictMode exceptions from
   * reading/writing in the UI thread. This method will block the current thread until the migration
   * is finished.
   */
  private static synchronized void migrateIfNecessary(final Context context) {
    if (migrationDone) {
      return;
    }

    // We deliberately perform the migration in the current thread (which
    // is likely the UI thread) as this is actually cheaper than enforcing a
    // context switch to another thread (see bug 940575).
    // Avoid strict mode warnings when doing so.
    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
    StrictMode.allowThreadDiskWrites();
    try {
      performMigration(context);
    } finally {
      StrictMode.setThreadPolicy(savedPolicy);
    }

    migrationDone = true;
  }
  /** Saves the tab data out to a file. */
  void saveState(File activityDirectory) {
    File tabFile = getTabFile(activityDirectory, getId());

    FileOutputStream foutput = null;
    // Temporarily allowing disk access while fixing. TODO: http://crbug.com/525781
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
    StrictMode.allowThreadDiskWrites();
    try {
      foutput = new FileOutputStream(tabFile);
      TabState.saveState(foutput, getState(), false);
    } catch (FileNotFoundException exception) {
      Log.e(TAG, "Failed to save out tab state.", exception);
    } catch (IOException exception) {
      Log.e(TAG, "Failed to save out tab state.", exception);
    } finally {
      StreamUtil.closeQuietly(foutput);
      StrictMode.setThreadPolicy(oldPolicy);
    }
  }
Example #8
0
  /**
   * Returns a URI that points at the file.
   *
   * @param file File to get a URI for.
   * @return URI that points at that file, either as a content:// URI or a file:// URI.
   */
  public static Uri getUriForItem(File file) {
    Uri uri = null;

    // #getContentUriFromFile causes a disk read when it calls into FileProvider#getUriForFile.
    // Obtaining a content URI is on the critical path for creating a share intent after the
    // user taps on the share button, so even if we were to run this method on a background
    // thread we would have to wait. As it depends on user-selected items, we cannot
    // know/preload which URIs we need until the user presses share.
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
    try {
      // Try to obtain a content:// URI, which is preferred to a file:// URI so that
      // receiving apps don't attempt to determine the file's mime type (which often fails).
      uri = ContentUriUtils.getContentUriFromFile(ContextUtils.getApplicationContext(), file);
    } catch (IllegalArgumentException e) {
      Log.e(TAG, "Could not create content uri: " + e);
    }
    StrictMode.setThreadPolicy(oldPolicy);

    if (uri == null) uri = Uri.fromFile(file);

    return uri;
  }
  public void update() {
    if (DEBUG) Slog.v(TAG, "Update: " + this);

    final long nowUptime = SystemClock.uptimeMillis();
    final long nowRealtime = SystemClock.elapsedRealtime();
    final long nowWallTime = System.currentTimeMillis();

    final long[] sysCpu = mSystemCpuData;
    if (Process.readProcFile("/proc/stat", SYSTEM_CPU_FORMAT, null, sysCpu, null)) {
      // Total user time is user + nice time.
      final long usertime = (sysCpu[0] + sysCpu[1]) * mJiffyMillis;
      // Total system time is simply system time.
      final long systemtime = sysCpu[2] * mJiffyMillis;
      // Total idle time is simply idle time.
      final long idletime = sysCpu[3] * mJiffyMillis;
      // Total irq time is iowait + irq + softirq time.
      final long iowaittime = sysCpu[4] * mJiffyMillis;
      final long irqtime = sysCpu[5] * mJiffyMillis;
      final long softirqtime = sysCpu[6] * mJiffyMillis;

      // This code is trying to avoid issues with idle time going backwards,
      // but currently it gets into situations where it triggers most of the time. :(
      if (true
          || (usertime >= mBaseUserTime
              && systemtime >= mBaseSystemTime
              && iowaittime >= mBaseIoWaitTime
              && irqtime >= mBaseIrqTime
              && softirqtime >= mBaseSoftIrqTime
              && idletime >= mBaseIdleTime)) {
        mRelUserTime = (int) (usertime - mBaseUserTime);
        mRelSystemTime = (int) (systemtime - mBaseSystemTime);
        mRelIoWaitTime = (int) (iowaittime - mBaseIoWaitTime);
        mRelIrqTime = (int) (irqtime - mBaseIrqTime);
        mRelSoftIrqTime = (int) (softirqtime - mBaseSoftIrqTime);
        mRelIdleTime = (int) (idletime - mBaseIdleTime);
        mRelStatsAreGood = true;

        if (DEBUG) {
          Slog.i(
              "Load",
              "Total U:"
                  + (sysCpu[0] * mJiffyMillis)
                  + " N:"
                  + (sysCpu[1] * mJiffyMillis)
                  + " S:"
                  + (sysCpu[2] * mJiffyMillis)
                  + " I:"
                  + (sysCpu[3] * mJiffyMillis)
                  + " W:"
                  + (sysCpu[4] * mJiffyMillis)
                  + " Q:"
                  + (sysCpu[5] * mJiffyMillis)
                  + " O:"
                  + (sysCpu[6] * mJiffyMillis));
          Slog.i(
              "Load",
              "Rel U:"
                  + mRelUserTime
                  + " S:"
                  + mRelSystemTime
                  + " I:"
                  + mRelIdleTime
                  + " Q:"
                  + mRelIrqTime);
        }

        mBaseUserTime = usertime;
        mBaseSystemTime = systemtime;
        mBaseIoWaitTime = iowaittime;
        mBaseIrqTime = irqtime;
        mBaseSoftIrqTime = softirqtime;
        mBaseIdleTime = idletime;

      } else {
        mRelUserTime = 0;
        mRelSystemTime = 0;
        mRelIoWaitTime = 0;
        mRelIrqTime = 0;
        mRelSoftIrqTime = 0;
        mRelIdleTime = 0;
        mRelStatsAreGood = false;
        Slog.w(TAG, "/proc/stats has gone backwards; skipping CPU update");
        return;
      }
    }

    mLastSampleTime = mCurrentSampleTime;
    mCurrentSampleTime = nowUptime;
    mLastSampleRealTime = mCurrentSampleRealTime;
    mCurrentSampleRealTime = nowRealtime;
    mLastSampleWallTime = mCurrentSampleWallTime;
    mCurrentSampleWallTime = nowWallTime;

    final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
    try {
      mCurPids = collectStats("/proc", -1, mFirst, mCurPids, mProcStats);
    } finally {
      StrictMode.setThreadPolicy(savedPolicy);
    }

    final float[] loadAverages = mLoadAverageData;
    if (Process.readProcFile("/proc/loadavg", LOAD_AVERAGE_FORMAT, null, null, loadAverages)) {
      float load1 = loadAverages[0];
      float load5 = loadAverages[1];
      float load15 = loadAverages[2];
      if (load1 != mLoad1 || load5 != mLoad5 || load15 != mLoad15) {
        mLoad1 = load1;
        mLoad5 = load5;
        mLoad15 = load15;
        onLoadChanged(load1, load5, load15);
      }
    }

    if (DEBUG)
      Slog.i(
          TAG, "*** TIME TO COLLECT STATS: " + (SystemClock.uptimeMillis() - mCurrentSampleTime));

    mWorkingProcsSorted = false;
    mFirst = false;
  }
  @Override
  public Notification build() {
    // A note about RemoteViews and updating notifications. When a notification is passed to the
    // {@code NotificationManager} with the same tag and id as a previous notification, an
    // in-place update will be performed. In that case, the actions of all new
    // {@link RemoteViews} will be applied to the views of the old notification. This is safe
    // for actions that overwrite old values such as setting the text of a {@code TextView}, but
    // care must be taken for additive actions. Especially in the case of
    // {@link RemoteViews#addView} the result could be to append new views below stale ones. In
    // that case {@link RemoteViews#removeAllViews} must be called before adding new ones.
    RemoteViews compactView = new RemoteViews(mContext.getPackageName(), R.layout.web_notification);
    RemoteViews bigView = new RemoteViews(mContext.getPackageName(), R.layout.web_notification_big);

    float fontScale = mContext.getResources().getConfiguration().fontScale;
    bigView.setInt(R.id.body, "setMaxLines", calculateMaxBodyLines(fontScale));
    int scaledPadding =
        calculateScaledPadding(fontScale, mContext.getResources().getDisplayMetrics());
    String formattedTime = "";

    // Temporarily allowing disk access. TODO: Fix. See http://crbug.com/577185
    StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
    StrictMode.allowThreadDiskWrites();
    try {
      long time = SystemClock.elapsedRealtime();
      formattedTime = DateFormat.getTimeFormat(mContext).format(new Date());
      RecordHistogram.recordTimesHistogram(
          "Android.StrictMode.NotificationUIBuildTime",
          SystemClock.elapsedRealtime() - time,
          TimeUnit.MILLISECONDS);
    } finally {
      StrictMode.setThreadPolicy(oldPolicy);
    }

    for (RemoteViews view : new RemoteViews[] {compactView, bigView}) {
      view.setTextViewText(R.id.time, formattedTime);
      view.setTextViewText(R.id.title, mTitle);
      view.setTextViewText(R.id.body, mBody);
      view.setTextViewText(R.id.origin, mOrigin);
      view.setImageViewBitmap(R.id.icon, getNormalizedLargeIcon());
      view.setViewPadding(R.id.title, 0, scaledPadding, 0, 0);
      view.setViewPadding(R.id.body_container, 0, scaledPadding, 0, scaledPadding);
      addWorkProfileBadge(view);

      int smallIconId = useMaterial() ? R.id.small_icon_overlay : R.id.small_icon_footer;
      view.setViewVisibility(smallIconId, View.VISIBLE);
      if (mSmallIconBitmap != null) {
        view.setImageViewBitmap(smallIconId, mSmallIconBitmap);
      } else {
        view.setImageViewResource(smallIconId, mSmallIconId);
      }
    }
    addActionButtons(bigView);
    configureSettingsButton(bigView);

    // Note: this is not a NotificationCompat builder so be mindful of the
    // API level of methods you call on the builder.
    Notification.Builder builder = new Notification.Builder(mContext);
    builder.setTicker(mTickerText);
    builder.setContentIntent(mContentIntent);
    builder.setDeleteIntent(mDeleteIntent);
    builder.setDefaults(mDefaults);
    builder.setVibrate(mVibratePattern);
    builder.setWhen(mTimestamp);
    builder.setOnlyAlertOnce(!mRenotify);
    builder.setContent(compactView);

    // Some things are duplicated in the builder to ensure the notification shows correctly on
    // Wear devices and custom lock screens.
    builder.setContentTitle(mTitle);
    builder.setContentText(mBody);
    builder.setSubText(mOrigin);
    builder.setLargeIcon(getNormalizedLargeIcon());
    setSmallIconOnBuilder(builder, mSmallIconId, mSmallIconBitmap);
    for (Action action : mActions) {
      addActionToBuilder(builder, action);
    }
    if (mSettingsAction != null) {
      addActionToBuilder(builder, mSettingsAction);
    }
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      // Notification.Builder.setPublicVersion was added in Android L.
      builder.setPublicVersion(createPublicNotification(mContext));
    }

    Notification notification = builder.build();
    notification.bigContentView = bigView;
    return notification;
  }