Fixed some strict mode violations.

Many strict mode violations are due to use of shared preferences on main thread, so we now warm up shared preferences in bypass mode in DialtactsActivity.onCreate. (Note that this shouldn't slow it down because we were already accessing them but without bypassing strict mode.)

I also added a new "storage" module which caches device protected shared prefs. Before we were not caching them and every access was resulting in a disk access, because #createDeviceProtectedStorageContext returns a new context for each call. (Note that this change is required for warming those prefs to work.)

Note that warming up prefs doesn't fix cases where prefs are read from jobs, services, or Application#onCreate (because those things can happen before DialtactsActivity#onCreate) so there is still a need to bypass in those specific places.

Finally, there were various other violations which we now bypass though we probably shouldn't; I'm considering these as being grandfathered in and it would be nice to fix them at some point but today I'd like to just get the app into a usable state so devs can keep strict mode enabled.

Bug: 64118795
Test: manually navigated bugfood build and observed no/fewer crashes
PiperOrigin-RevId: 165031607
Change-Id: I336212a650a7bd93915ebe56a08e976d37818d68
diff --git a/java/com/android/contacts/common/preference/ContactsPreferences.java b/java/com/android/contacts/common/preference/ContactsPreferences.java
index 7f0d99a..2bdf5c8 100644
--- a/java/com/android/contacts/common/preference/ContactsPreferences.java
+++ b/java/com/android/contacts/common/preference/ContactsPreferences.java
@@ -27,6 +27,7 @@
 import android.text.TextUtils;
 import com.android.contacts.common.R;
 import com.android.contacts.common.model.account.AccountWithDataSet;
+import com.android.dialer.strictmode.DialerStrictMode;
 
 /** Manages user preferences for contacts. */
 public class ContactsPreferences implements OnSharedPreferenceChangeListener {
@@ -77,11 +78,11 @@
     maybeMigrateSystemSettings();
   }
 
-  public boolean isSortOrderUserChangeable() {
+  private boolean isSortOrderUserChangeable() {
     return mContext.getResources().getBoolean(R.bool.config_sort_order_user_changeable);
   }
 
-  public int getDefaultSortOrder() {
+  private int getDefaultSortOrder() {
     if (mContext.getResources().getBoolean(R.bool.config_default_sort_order_primary)) {
       return SORT_ORDER_PRIMARY;
     } else {
@@ -103,14 +104,14 @@
     mSortOrder = sortOrder;
     final Editor editor = mPreferences.edit();
     editor.putInt(SORT_ORDER_KEY, sortOrder);
-    editor.commit();
+    DialerStrictMode.bypass(editor::commit);
   }
 
-  public boolean isDisplayOrderUserChangeable() {
+  private boolean isDisplayOrderUserChangeable() {
     return mContext.getResources().getBoolean(R.bool.config_display_order_user_changeable);
   }
 
-  public int getDefaultDisplayOrder() {
+  private int getDefaultDisplayOrder() {
     if (mContext.getResources().getBoolean(R.bool.config_default_display_order_primary)) {
       return DISPLAY_ORDER_PRIMARY;
     } else {
@@ -132,14 +133,14 @@
     mDisplayOrder = displayOrder;
     final Editor editor = mPreferences.edit();
     editor.putInt(DISPLAY_ORDER_KEY, displayOrder);
-    editor.commit();
+    DialerStrictMode.bypass(editor::commit);
   }
 
-  public boolean isDefaultAccountUserChangeable() {
+  private boolean isDefaultAccountUserChangeable() {
     return mContext.getResources().getBoolean(R.bool.config_default_account_user_changeable);
   }
 
-  public String getDefaultAccount() {
+  private String getDefaultAccount() {
     if (!isDefaultAccountUserChangeable()) {
       return mDefaultAccount;
     }
@@ -153,7 +154,7 @@
     return mDefaultAccount;
   }
 
-  public void setDefaultAccount(AccountWithDataSet accountWithDataSet) {
+  private void setDefaultAccount(AccountWithDataSet accountWithDataSet) {
     mDefaultAccount = accountWithDataSet == null ? null : accountWithDataSet.name;
     final Editor editor = mPreferences.edit();
     if (TextUtils.isEmpty(mDefaultAccount)) {
@@ -162,7 +163,7 @@
       editor.putString(mDefaultAccountKey, accountWithDataSet.stringify());
     }
     editor.putBoolean(mDefaultAccountSavedKey, true);
-    editor.commit();
+    DialerStrictMode.bypass(editor::commit);
   }
 
   public void registerChangeListener(ChangeListener listener) {
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 99a16d9..a5d6502 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -31,6 +31,7 @@
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.preference.PreferenceManager;
 import android.provider.CallLog.Calls;
 import android.speech.RecognizerIntent;
 import android.support.annotation.MainThread;
@@ -120,6 +121,7 @@
 import com.android.dialer.simulator.SimulatorComponent;
 import com.android.dialer.smartdial.SmartDialNameMatcher;
 import com.android.dialer.smartdial.SmartDialPrefix;
+import com.android.dialer.strictmode.DialerStrictMode;
 import com.android.dialer.telecom.TelecomUtil;
 import com.android.dialer.util.DialerUtils;
 import com.android.dialer.util.PermissionsUtil;
@@ -387,6 +389,8 @@
     Trace.beginSection(TAG + " onCreate");
     super.onCreate(savedInstanceState);
 
+    warmupSharedPrefs();
+
     mFirstLaunch = true;
     isLastTabEnabled = ConfigProviderBindings.get(this).getBoolean("last_tab_enabled", false);
 
@@ -503,6 +507,32 @@
     Trace.endSection();
   }
 
+  /**
+   * We frequently access shared preferences on the main thread, which causes strict mode
+   * violations. Warm up the shared preferences here 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 void warmupSharedPrefs() {
+    DialerStrictMode.bypass(
+        () -> {
+          // From credential-encrypted (CE) storage, i.e.:
+          //    /data/data/com.google.android.dialer/shared_prefs
+
+          // com.google.android.dialer_preferences.xml
+          PreferenceManager.getDefaultSharedPreferences(this);
+
+          // com.google.android.dialer.xml
+          getSharedPreferences(getPackageName(), Context.MODE_PRIVATE);
+
+          // From device-encrypted (DE) storage, i.e.:
+          //   /data/user_de/0/com.android.dialer/shared_prefs/
+
+          // com.google.android.dialer_preferences.xml
+          DialerUtils.getDefaultSharedPreferenceForDeviceProtectedStorageContext(this);
+        });
+  }
+
   @NonNull
   private ActionBar getActionBarSafely() {
     return Assert.isNotNull(getSupportActionBar());
@@ -855,7 +885,7 @@
 
     Assert.isNotNull(mListsFragment.getView()).animate().alpha(0).withLayer();
 
-    //adjust the title, so the user will know where we're at when the activity start/resumes.
+    // adjust the title, so the user will know where we're at when the activity start/resumes.
     setTitle(R.string.launcherDialpadActivityLabel);
   }
 
@@ -917,7 +947,7 @@
         exitSearchUi();
       }
     }
-    //reset the title to normal.
+    // reset the title to normal.
     setTitle(R.string.launcherActivityLabel);
   }
 
diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
index 6a7c588..c4adb37 100644
--- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
+++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java
@@ -24,6 +24,7 @@
 import com.android.dialer.inject.ContextModule;
 import com.android.dialer.lightbringer.stub.StubLightbringerModule;
 import com.android.dialer.simulator.impl.SimulatorModule;
+import com.android.dialer.storage.StorageModule;
 import com.android.incallui.calllocation.stub.StubCallLocationModule;
 import com.android.incallui.maps.stub.StubMapsModule;
 import com.android.voicemail.impl.VoicemailModule;
@@ -39,6 +40,7 @@
     DialerExecutorModule.class,
     SharedPrefConfigProviderModule.class,
     SimulatorModule.class,
+    StorageModule.class,
     StubCallLocationModule.class,
     StubEnrichedCallModule.class,
     StubMapsModule.class,
diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
index 8ac071f..1349564 100644
--- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
+++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java
@@ -24,6 +24,7 @@
 import com.android.dialer.lightbringer.LightbringerComponent;
 import com.android.dialer.main.MainComponent;
 import com.android.dialer.simulator.SimulatorComponent;
+import com.android.dialer.storage.StorageComponent;
 import com.android.incallui.calllocation.CallLocationComponent;
 import com.android.incallui.maps.MapsComponent;
 import com.android.voicemail.VoicemailComponent;
@@ -42,5 +43,6 @@
         EnrichedCallComponent.HasComponent,
         MapsComponent.HasComponent,
         SimulatorComponent.HasComponent,
+        StorageComponent.HasComponent,
         VoicemailComponent.HasComponent,
         LightbringerComponent.HasComponent {}
diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
index 2b4de97..570b569 100644
--- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
+++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java
@@ -24,6 +24,7 @@
 import com.android.dialer.inject.ContextModule;
 import com.android.dialer.lightbringer.stub.StubLightbringerModule;
 import com.android.dialer.simulator.impl.SimulatorModule;
+import com.android.dialer.storage.StorageModule;
 import com.android.incallui.calllocation.impl.CallLocationModule;
 import com.android.incallui.maps.impl.MapsModule;
 import com.android.voicemail.impl.VoicemailModule;
@@ -43,6 +44,7 @@
     DialerExecutorModule.class,
     SharedPrefConfigProviderModule.class,
     SimulatorModule.class,
+    StorageModule.class,
     StubEnrichedCallModule.class,
     MapsModule.class,
     VoicemailModule.class,
diff --git a/java/com/android/dialer/blocking/FilteredNumberCompat.java b/java/com/android/dialer/blocking/FilteredNumberCompat.java
index e104c4f..548c965 100644
--- a/java/com/android/dialer/blocking/FilteredNumberCompat.java
+++ b/java/com/android/dialer/blocking/FilteredNumberCompat.java
@@ -38,6 +38,7 @@
 import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
 import com.android.dialer.database.FilteredNumberContract.FilteredNumberSources;
 import com.android.dialer.database.FilteredNumberContract.FilteredNumberTypes;
+import com.android.dialer.strictmode.DialerStrictMode;
 import com.android.dialer.telecom.TelecomUtil;
 import java.util.ArrayList;
 import java.util.List;
@@ -124,8 +125,10 @@
    *     android.provider.BlockedNumberContract} blocking, {@code false} otherwise.
    */
   public static boolean hasMigratedToNewBlocking(Context context) {
-    return PreferenceManager.getDefaultSharedPreferences(context)
-        .getBoolean(HAS_MIGRATED_TO_NEW_BLOCKING_KEY, false);
+    return DialerStrictMode.bypass(
+        () ->
+            PreferenceManager.getDefaultSharedPreferences(context)
+                .getBoolean(HAS_MIGRATED_TO_NEW_BLOCKING_KEY, false));
   }
 
   /**
diff --git a/java/com/android/dialer/storage/DeviceProtected.java b/java/com/android/dialer/storage/DeviceProtected.java
new file mode 100644
index 0000000..862259a
--- /dev/null
+++ b/java/com/android/dialer/storage/DeviceProtected.java
@@ -0,0 +1,22 @@
+/*
+ * 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.storage;
+
+import javax.inject.Qualifier;
+
+/** Annotation for retrieving device protected storage objects. */
+@Qualifier
+public @interface DeviceProtected {}
diff --git a/java/com/android/dialer/storage/StorageComponent.java b/java/com/android/dialer/storage/StorageComponent.java
new file mode 100644
index 0000000..51afea7
--- /dev/null
+++ b/java/com/android/dialer/storage/StorageComponent.java
@@ -0,0 +1,40 @@
+/*
+ * 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.storage;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import com.android.dialer.inject.HasRootComponent;
+import dagger.Subcomponent;
+
+/** Dagger component for storage. */
+@Subcomponent
+public abstract class StorageComponent {
+
+  public abstract @DeviceProtected SharedPreferences deviceProtectedSharedPreferences();
+
+  public static StorageComponent get(Context context) {
+    return ((StorageComponent.HasComponent)
+            ((HasRootComponent) context.getApplicationContext()).component())
+        .storageComponent();
+  }
+
+  /** Used to refer to the root application component. */
+  public interface HasComponent {
+    StorageComponent storageComponent();
+  }
+}
diff --git a/java/com/android/dialer/storage/StorageModule.java b/java/com/android/dialer/storage/StorageModule.java
new file mode 100644
index 0000000..8c97980
--- /dev/null
+++ b/java/com/android/dialer/storage/StorageModule.java
@@ -0,0 +1,46 @@
+/*
+ * 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.storage;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.support.v4.content.ContextCompat;
+import com.android.dialer.inject.ApplicationContext;
+import dagger.Module;
+import dagger.Provides;
+import javax.inject.Singleton;
+
+/** Module for the storage component. */
+@Module
+public class StorageModule {
+
+  @Provides
+  @Singleton
+  @DeviceProtected
+  static SharedPreferences provideDeviceProtectedSharedPreferences(
+      @ApplicationContext Context appContext) {
+    // #createDeviceProtectedStorageContext returns a new context each time, so we cache the shared
+    // preferences object in order to avoid accessing disk for every operation.
+    Context deviceProtectedContext = ContextCompat.createDeviceProtectedStorageContext(appContext);
+
+    // ContextCompat.createDeviceProtectedStorageContext(context) returns null on pre-N, thus fall
+    // back to regular default shared preference for pre-N devices since devices protected context
+    // is not available.
+    return PreferenceManager.getDefaultSharedPreferences(
+        deviceProtectedContext != null ? deviceProtectedContext : appContext);
+  }
+}
diff --git a/java/com/android/dialer/strictmode/DialerStrictMode.java b/java/com/android/dialer/strictmode/DialerStrictMode.java
index 3c31aa9..ad1a6c6 100644
--- a/java/com/android/dialer/strictmode/DialerStrictMode.java
+++ b/java/com/android/dialer/strictmode/DialerStrictMode.java
@@ -103,4 +103,22 @@
       enableDeathPenalty();
     }
   }
+
+  /**
+   * Convenience method for disabling and enabling the death penalty using lambdas.
+   *
+   * <p>For example:
+   *
+   * <p><code>
+   *   DialerStrictMode.bypass(() -> doDiskAccessOnMainThread());
+   * </code>
+   */
+  public static void bypass(Runnable runnable) {
+    disableDeathPenalty();
+    try {
+      runnable.run();
+    } finally {
+      enableDeathPenalty();
+    }
+  }
 }
diff --git a/java/com/android/dialer/util/DialerUtils.java b/java/com/android/dialer/util/DialerUtils.java
index 63f870e..f38c650 100644
--- a/java/com/android/dialer/util/DialerUtils.java
+++ b/java/com/android/dialer/util/DialerUtils.java
@@ -38,6 +38,7 @@
 import android.widget.Toast;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.LogUtil;
+import com.android.dialer.storage.StorageComponent;
 import com.android.dialer.telecom.TelecomUtil;
 import java.io.File;
 import java.util.Iterator;
@@ -233,14 +234,9 @@
   public static SharedPreferences getDefaultSharedPreferenceForDeviceProtectedStorageContext(
       @NonNull Context context) {
     Assert.isNotNull(context);
-    Context deviceProtectedContext =
-        ContextCompat.isDeviceProtectedStorage(context)
-            ? context
-            : ContextCompat.createDeviceProtectedStorageContext(context);
-    // ContextCompat.createDeviceProtectedStorageContext(context) returns null on pre-N, thus fall
-    // back to regular default shared preference for pre-N devices since devices protected context
-    // is not available.
-    return PreferenceManager.getDefaultSharedPreferences(
-        deviceProtectedContext != null ? deviceProtectedContext : context);
+    if (ContextCompat.isDeviceProtectedStorage(context)) {
+      return PreferenceManager.getDefaultSharedPreferences(context);
+    }
+    return StorageComponent.get(context.getApplicationContext()).deviceProtectedSharedPreferences();
   }
 }
diff --git a/java/com/android/dialer/util/IntentUtil.java b/java/com/android/dialer/util/IntentUtil.java
index 2f265b5..f453966 100644
--- a/java/com/android/dialer/util/IntentUtil.java
+++ b/java/com/android/dialer/util/IntentUtil.java
@@ -31,7 +31,8 @@
   }
 
   public static Intent getNewContactIntent() {
-    return new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI);
+    return new Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI)
+        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
   }
 
   public static Intent getNewContactIntent(CharSequence phoneNumber) {
diff --git a/java/com/android/incallui/CallerInfoAsyncQuery.java b/java/com/android/incallui/CallerInfoAsyncQuery.java
index d620d47..858d0f4 100644
--- a/java/com/android/incallui/CallerInfoAsyncQuery.java
+++ b/java/com/android/incallui/CallerInfoAsyncQuery.java
@@ -41,6 +41,7 @@
 import com.android.dialer.phonenumbercache.CachedNumberLookupService.CachedContactInfo;
 import com.android.dialer.phonenumbercache.ContactInfoHelper;
 import com.android.dialer.phonenumbercache.PhoneNumberCache;
+import com.android.dialer.strictmode.DialerStrictMode;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -189,7 +190,7 @@
       CallerInfo info,
       OnQueryCompleteListener listener,
       Object cookie) {
-    long[] directoryIds = getDirectoryIds(context);
+    long[] directoryIds = DialerStrictMode.bypass(() -> getDirectoryIds(context));
     int size = directoryIds.length;
     if (size == 0) {
       return false;
diff --git a/java/com/android/incallui/incall/impl/InCallFragment.java b/java/com/android/incallui/incall/impl/InCallFragment.java
index 1730c80..7e39ceb 100644
--- a/java/com/android/incallui/incall/impl/InCallFragment.java
+++ b/java/com/android/incallui/incall/impl/InCallFragment.java
@@ -44,6 +44,7 @@
 import com.android.dialer.logging.DialerImpression;
 import com.android.dialer.logging.Logger;
 import com.android.dialer.multimedia.MultimediaData;
+import com.android.dialer.strictmode.DialerStrictMode;
 import com.android.dialer.widget.LockableViewPager;
 import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment;
 import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment.AudioRouteSelectorPresenter;
@@ -139,7 +140,10 @@
       @Nullable ViewGroup viewGroup,
       @Nullable Bundle bundle) {
     LogUtil.i("InCallFragment.onCreateView", null);
-    final View view = layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false);
+    // Bypass to avoid StrictModeResourceMismatchViolation
+    final View view =
+        DialerStrictMode.bypass(
+            () -> layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false));
     contactGridManager =
         new ContactGridManager(
             view,
diff --git a/java/com/android/voicemail/impl/VoicemailStatus.java b/java/com/android/voicemail/impl/VoicemailStatus.java
index ec1ab4e..5553cf5 100644
--- a/java/com/android/voicemail/impl/VoicemailStatus.java
+++ b/java/com/android/voicemail/impl/VoicemailStatus.java
@@ -24,6 +24,7 @@
 import android.provider.VoicemailContract.Status;
 import android.support.annotation.Nullable;
 import android.telecom.PhoneAccountHandle;
+import com.android.dialer.strictmode.DialerStrictMode;
 
 public class VoicemailStatus {
 
@@ -99,7 +100,7 @@
       ContentResolver contentResolver = mContext.getContentResolver();
       Uri statusUri = VoicemailContract.Status.buildSourceUri(mContext.getPackageName());
       try {
-        contentResolver.insert(statusUri, mValues);
+        DialerStrictMode.bypass(() -> contentResolver.insert(statusUri, mValues));
       } catch (IllegalArgumentException iae) {
         VvmLog.e(TAG, "apply :: failed to insert content resolver ", iae);
         mValues.clear();
diff --git a/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java
index 18b2b92..1624ce5 100644
--- a/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java
+++ b/java/com/android/voicemail/impl/configui/ConfigOverrideFragment.java
@@ -35,6 +35,7 @@
 import android.text.TextUtils;
 import com.android.dialer.common.Assert;
 import com.android.dialer.common.concurrent.ThreadUtil;
+import com.android.dialer.strictmode.DialerStrictMode;
 import com.android.voicemail.VoicemailComponent;
 
 /**
@@ -126,8 +127,10 @@
   }
 
   public static boolean isOverridden(Context context) {
-    return PreferenceManager.getDefaultSharedPreferences(context)
-        .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false);
+    return DialerStrictMode.bypass(
+        () ->
+            PreferenceManager.getDefaultSharedPreferences(context)
+                .getBoolean(context.getString(R.string.vvm_config_override_enabled_key), false));
   }
 
   public static PersistableBundle getConfig(Context context) {
diff --git a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java
index 107234e..baf5804 100644
--- a/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java
+++ b/java/com/android/voicemail/impl/scheduling/TaskSchedulerJobService.java
@@ -30,6 +30,7 @@
 import android.preference.PreferenceManager;
 import android.support.annotation.MainThread;
 import com.android.dialer.constants.ScheduledJobIds;
+import com.android.dialer.strictmode.DialerStrictMode;
 import com.android.voicemail.impl.Assert;
 import com.android.voicemail.impl.VvmLog;
 import java.util.ArrayList;
@@ -58,7 +59,8 @@
   public boolean onStartJob(JobParameters params) {
     int jobId = params.getTransientExtras().getInt(EXTRA_JOB_ID);
     int expectedJobId =
-        PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0);
+        DialerStrictMode.bypass(
+            () -> PreferenceManager.getDefaultSharedPreferences(this).getInt(EXPECTED_JOB_ID, 0));
     if (jobId != expectedJobId) {
       VvmLog.e(
           TAG, "Job " + jobId + " is not the last scheduled job " + expectedJobId + ", ignoring");