diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-08-31 16:17:04 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-08-31 16:17:04 +0000 |
commit | c39ea3c55fac807c0b98aabdf56c70dc8a49036c (patch) | |
tree | e282668a9587cf6c1ec7b604dea860400c75c6c7 /java/com/android/dialer/strictmode/DialerStrictMode.java | |
parent | 68038172793ee0e2ab3e2e56ddfbeb82879d1f58 (diff) | |
parent | 2ca4318cc1ee57dda907ba2069bd61d162b1baef (diff) |
Merge "Update Dialer source to latest internal Google revision."
Diffstat (limited to 'java/com/android/dialer/strictmode/DialerStrictMode.java')
-rw-r--r-- | java/com/android/dialer/strictmode/DialerStrictMode.java | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/java/com/android/dialer/strictmode/DialerStrictMode.java b/java/com/android/dialer/strictmode/DialerStrictMode.java new file mode 100644 index 000000000..f895f7c46 --- /dev/null +++ b/java/com/android/dialer/strictmode/DialerStrictMode.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.dialer.strictmode; + +import android.app.Application; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.os.StrictMode; +import android.os.StrictMode.ThreadPolicy; +import android.os.StrictMode.VmPolicy; +import android.preference.PreferenceManager; +import android.support.annotation.AnyThread; +import android.support.annotation.MainThread; +import android.support.v4.os.UserManagerCompat; +import com.android.dialer.buildtype.BuildType; +import com.android.dialer.function.Supplier; +import com.android.dialer.util.DialerUtils; + +/** Enables strict mode for the application, and provides means of temporarily disabling it. */ +public final class DialerStrictMode { + + private static final VmPolicy VM_DEATH_PENALTY = + new StrictMode.VmPolicy.Builder().penaltyLog().penaltyDeath().build(); + + private static final ThreadPolicy THREAD_LOG_PENALTY = + new StrictMode.ThreadPolicy.Builder().penaltyLog().build(); + private static final ThreadPolicy THREAD_DEATH_PENALTY = + new StrictMode.ThreadPolicy.Builder().penaltyLog().penaltyDeath().build(); + + private DialerStrictMode() {} + + /** Initializes strict mode on application start. */ + @MainThread + public static void onApplicationCreate(Application application) { + if (isStrictModeAllowed()) { + warmupSharedPrefs(application); + StrictModeUtils.setRecommendedMainThreadPolicy(THREAD_DEATH_PENALTY); + StrictModeUtils.setRecommendedVMPolicy(VM_DEATH_PENALTY); + + // Because Android resets StrictMode policies after Application.onCreate is done, we set it + // again right after. + // See cl/105932355 for the discussion. + // See b/36951662 for the public bug. + Handler handler = new Handler(Looper.myLooper()); + handler.postAtFrontOfQueue( + () -> StrictModeUtils.setRecommendedMainThreadPolicy(THREAD_DEATH_PENALTY)); + } + } + + /** + * We frequently access shared preferences on the main thread, which causes strict mode + * violations. When strict mode is allowed, warm up the shared preferences so that later uses of + * shared preferences access the in-memory versions and we don't have to bypass strict mode at + * every point in the application where shared preferences are accessed. + */ + private static void warmupSharedPrefs(Application application) { + // From credential-encrypted (CE) storage, i.e.: + // /data/data/com.android.dialer/shared_prefs + + if (UserManagerCompat.isUserUnlocked(application)) { + // <package_name>_preferences.xml + PreferenceManager.getDefaultSharedPreferences(application); + + // <package_name>.xml + application.getSharedPreferences(application.getPackageName(), Context.MODE_PRIVATE); + } + + // From device-encrypted (DE) storage, i.e.: + // /data/user_de/0/com.android.dialer/shared_prefs/ + + // <package_name>_preferences.xml + DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(application); + } + + private static boolean isStrictModeAllowed() { + return BuildType.get() == BuildType.BUGFOOD; + } + + private static boolean onMainThread() { + return Looper.getMainLooper().equals(Looper.myLooper()); + } + + /** + * Convenience method for disabling and enabling the thread policy death penalty using lambdas. + * + * <p>For example: + * + * <p><code> + * Value foo = DialerStrictMode.bypass(() -> doDiskAccessOnMainThreadReturningValue()); + * </code> + * + * <p>The thread policy is only mutated if this is called from the main thread. + */ + @AnyThread + public static <T> T bypass(Supplier<T> supplier) { + if (isStrictModeAllowed() && onMainThread()) { + ThreadPolicy originalPolicy = StrictMode.getThreadPolicy(); + StrictModeUtils.setRecommendedMainThreadPolicy(THREAD_LOG_PENALTY); + try { + return supplier.get(); + } finally { + StrictMode.setThreadPolicy(originalPolicy); + } + } + return supplier.get(); + } + + /** + * Convenience method for disabling and enabling the thread policy death penalty using lambdas. + * + * <p>For example: + * + * <p><code> + * DialerStrictMode.bypass(() -> doDiskAccessOnMainThread()); + * </code> + * + * <p>The thread policy is only mutated if this is called from the main thread. + */ + @AnyThread + public static void bypass(Runnable runnable) { + if (isStrictModeAllowed() && onMainThread()) { + ThreadPolicy originalPolicy = StrictMode.getThreadPolicy(); + StrictModeUtils.setRecommendedMainThreadPolicy(THREAD_LOG_PENALTY); + try { + runnable.run(); + } finally { + StrictMode.setThreadPolicy(originalPolicy); + } + } + runnable.run(); + } +} |