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); } }
/** * 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); } }
/** * 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); } }
/** * 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; }