Use ContactDisplayPreferencesStub when device is locked.

PreferenceManager.getDefaultSharedPreferences() can only be called when the device is unlocked. The module will lazily construct the impl.

Fix defaults for contact display preferences.

If the settings are accessed before the preferences are populated the wrong default value will be used.

Test: make
Bug: 111275389, 111051362
Change-Id: I29e34d61d529c91065aa3ef952d125d83cdee982
diff --git a/java/com/android/dialer/app/res/xml/display_options_settings.xml b/java/com/android/dialer/app/res/xml/display_options_settings.xml
index 60301db..f154122 100644
--- a/java/com/android/dialer/app/res/xml/display_options_settings.xml
+++ b/java/com/android/dialer/app/res/xml/display_options_settings.xml
@@ -25,7 +25,7 @@
       android:entries="@array/contact_sort_order_entries"
       android:entryValues="@array/contact_sort_order_values"
       android:title="@string/display_options_sort_list_by"
-      android:defaultValue="1"/>
+      android:defaultValue="@string/display_options_sort_by_given_name_value"/>
 
   <ListPreference
       android:dialogTitle="@string/display_options_view_names_as"
@@ -34,6 +34,6 @@
       android:entries="@array/contact_display_order_entries"
       android:entryValues="@array/contact_display_order_values"
       android:title="@string/display_options_view_names_as"
-      android:defaultValue="1"/>
+      android:defaultValue="@string/display_options_view_given_name_first_value"/>
 
 </PreferenceScreen>
diff --git a/java/com/android/dialer/contacts/ContactsModule.java b/java/com/android/dialer/contacts/ContactsModule.java
index 73731e5..2a27b76 100644
--- a/java/com/android/dialer/contacts/ContactsModule.java
+++ b/java/com/android/dialer/contacts/ContactsModule.java
@@ -16,22 +16,35 @@
 
 package com.android.dialer.contacts;
 
+import android.content.Context;
+import android.os.UserManager;
 import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences;
 import com.android.dialer.contacts.displaypreference.ContactDisplayPreferencesImpl;
+import com.android.dialer.contacts.displaypreference.ContactDisplayPreferencesStub;
 import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequester;
 import com.android.dialer.contacts.hiresphoto.HighResolutionPhotoRequesterImpl;
+import com.android.dialer.inject.ApplicationContext;
 import com.android.dialer.inject.DialerVariant;
 import com.android.dialer.inject.InstallIn;
 import dagger.Binds;
+import dagger.Lazy;
 import dagger.Module;
+import dagger.Provides;
 
 /** Module for standard {@link ContactsComponent} */
 @InstallIn(variants = {DialerVariant.DIALER_TEST})
 @Module
 public abstract class ContactsModule {
-  @Binds
-  public abstract ContactDisplayPreferences toContactDisplayPreferencesImpl(
-      ContactDisplayPreferencesImpl impl);
+  @Provides
+  public static ContactDisplayPreferences provideContactDisplayPreferences(
+      @ApplicationContext Context appContext,
+      Lazy<ContactDisplayPreferencesImpl> impl,
+      ContactDisplayPreferencesStub stub) {
+    if (appContext.getSystemService(UserManager.class).isUserUnlocked()) {
+      return impl.get();
+    }
+    return stub;
+  }
 
   @Binds
   public abstract HighResolutionPhotoRequester toHighResolutionPhotoRequesterImpl(
diff --git a/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java
index 6072cc1..4f67b17 100644
--- a/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java
+++ b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java
@@ -23,7 +23,10 @@
 import com.android.dialer.inject.ApplicationContext;
 import javax.inject.Inject;
 
-/** Implementation of {@link ContactDisplayPreferences} backed by a {@link SharedPreferences} */
+/**
+ * Implementation of {@link ContactDisplayPreferences} backed by a {@link SharedPreferences}. Can
+ * only be instantiated when the device is unlocked.
+ */
 public final class ContactDisplayPreferencesImpl implements ContactDisplayPreferences {
 
   private final Context appContext;
@@ -35,7 +38,7 @@
   ContactDisplayPreferencesImpl(@ApplicationContext Context appContext) {
     this.appContext = appContext;
     // @Unencrypted preference would be a better choice, but Android Preference only supports the
-    // default file. Names cannot be shown on @Unencrypted anyway.
+    // default file. Stub should be used instead when device is locked.
     this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
     displayOrderKey = appContext.getString(R.string.display_options_view_names_as_key);
     sortOrderKey = appContext.getString(R.string.display_options_sort_list_by_key);
diff --git a/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesStub.java b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesStub.java
new file mode 100644
index 0000000..a42a94b
--- /dev/null
+++ b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesStub.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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.contacts.displaypreference;
+
+import javax.inject.Inject;
+
+/**
+ * Stub implementation of {@link ContactDisplayPreferences} that always returns primary. Used when
+ * the device is locked and regular storage is not available.
+ */
+public final class ContactDisplayPreferencesStub implements ContactDisplayPreferences {
+
+  @Inject
+  ContactDisplayPreferencesStub() {}
+
+  @Override
+  public DisplayOrder getDisplayOrder() {
+    return DisplayOrder.PRIMARY;
+  }
+
+  @Override
+  public void setDisplayOrder(DisplayOrder displayOrder) {
+    // Do nothing
+  }
+
+  @Override
+  public SortOrder getSortOrder() {
+    return SortOrder.BY_PRIMARY;
+  }
+
+  @Override
+  public void setSortOrder(SortOrder sortOrder) {
+    // Do nothing
+  }
+}