Merge "Select SIM when calling back from call log."
diff --git a/Android.mk b/Android.mk
index b71f702..377ad7c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -433,6 +433,7 @@
 
 LOCAL_SRC_FILES := \
 	$(call all-java-files-under, $(BASE_DIR)/dialer/rootcomponentgenerator) \
+	      $(BASE_DIR)/dialer/inject/GenerateDaggerApp.java \
         $(BASE_DIR)/dialer/inject/DialerRootComponent.java \
         $(BASE_DIR)/dialer/inject/DialerVariant.java \
         $(BASE_DIR)/dialer/inject/HasRootComponent.java \
diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
index 28663c1..e3e9e7a 100644
--- a/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
@@ -19,6 +19,9 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.BottomSheetBehavior;
+import android.support.design.widget.BottomSheetBehavior.BottomSheetCallback;
 import android.support.design.widget.BottomSheetDialog;
 import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
@@ -26,6 +29,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.Window;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -49,9 +53,9 @@
       Context context,
       HistoryItemBottomSheetHeaderInfo historyItemBottomSheetHeaderInfo,
       List<HistoryItemActionModule> modules) {
-    super(context);
+    super(context, R.style.HistoryItemBottomSheet);
     this.modules = modules;
-    this.historyItemBottomSheetHeaderInfo = historyItemBottomSheetHeaderInfo;
+    this.historyItemBottomSheetHeaderInfo = Assert.isNotNull(historyItemBottomSheetHeaderInfo);
     setContentView(LayoutInflater.from(context).inflate(R.layout.sheet_layout, null));
   }
 
@@ -67,10 +71,10 @@
 
   @Override
   protected void onCreate(Bundle bundle) {
-    super.onCreate(bundle);
-    LinearLayout container = Assert.isNotNull(findViewById(R.id.action_container));
-    container.addView(getContactView(container));
+    setupWindow();
+    setupContactLayout();
 
+    LinearLayout container = Assert.isNotNull(findViewById(R.id.action_container));
     for (HistoryItemActionModule module : modules) {
       if (module instanceof DividerModule) {
         container.addView(getDividerView(container));
@@ -80,9 +84,20 @@
     }
   }
 
-  private View getContactView(ViewGroup container) {
-    LayoutInflater inflater = LayoutInflater.from(getContext());
-    View contactView = inflater.inflate(R.layout.contact_layout, container, false);
+  // Overrwrites the window size since Dialog's don't match parent.
+  private void setupWindow() {
+    Window window = getWindow();
+    if (window == null) {
+      return;
+    }
+    // TODO(calderwoodra): set the nav bar color
+    window.setLayout(
+        /* width = */ ViewGroup.LayoutParams.MATCH_PARENT,
+        /* height = */ ViewGroup.LayoutParams.MATCH_PARENT);
+  }
+
+  private void setupContactLayout() {
+    View contactView = Assert.isNotNull(findViewById(R.id.contact_layout_root));
 
     ContactPhotoView contactPhotoView = contactView.findViewById(R.id.contact_photo_view);
     contactPhotoView.setPhoto(historyItemBottomSheetHeaderInfo.getPhotoInfo());
@@ -97,7 +112,35 @@
       secondaryTextView.setVisibility(View.GONE);
       secondaryTextView.setText(null);
     }
-    return contactView;
+
+    View background = findViewById(android.support.design.R.id.touch_outside);
+    BottomSheetBehavior behavior =
+        BottomSheetBehavior.from(findViewById(android.support.design.R.id.design_bottom_sheet));
+    behavior.setBottomSheetCallback(
+        new BottomSheetCallback() {
+          @Override
+          public void onStateChanged(@NonNull View bottomSheet, int newState) {
+            if (newState == BottomSheetBehavior.STATE_HIDDEN) {
+              cancel();
+              return;
+            }
+
+            // If the bottomsheet can expand to full screen, set the header's elevation when it's
+            // fully expanded.
+            if (background.getHeight() == bottomSheet.getHeight()) {
+              contactView.setElevation(
+                  newState == BottomSheetBehavior.STATE_EXPANDED
+                      ? getContext()
+                          .getResources()
+                          .getDimensionPixelSize(R.dimen.contact_actions_header_elevation)
+                      : 0);
+              // TODO(calderwoodra): set the status bar color when expanded, else translucent
+            }
+          }
+
+          @Override
+          public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
+        });
   }
 
   private View getDividerView(ViewGroup container) {
diff --git a/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
index f2dc8c7..721740f 100644
--- a/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
+++ b/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
@@ -15,13 +15,15 @@
  ~ limitations under the License
  -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/contact_layout_root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:layout_marginTop="8dp"
-    android:layout_marginBottom="12dp"
-    android:layout_marginEnd="8dp"
+    android:paddingTop="12dp"
+    android:paddingBottom="12dp"
+    android:paddingEnd="8dp"
     android:gravity="center_vertical"
-    android:orientation="horizontal">
+    android:orientation="horizontal"
+    android:background="#FFFFFF">
 
   <com.android.dialer.widget.ContactPhotoView
       android:id="@+id/contact_photo_view"
diff --git a/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
index 6984367..006302e 100644
--- a/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
+++ b/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
@@ -16,9 +16,24 @@
  -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/action_container"
+    android:id="@+id/history_item_actions_bottom_sheet_root"
     android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:paddingTop="4dp"
-    android:paddingBottom="8dp"/>
+    android:layout_height="match_parent">
+
+  <include layout="@layout/contact_layout"/>
+
+  <android.support.v4.widget.NestedScrollView
+      android:id="@+id/history_actions_scroll_view"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content">
+
+      <LinearLayout
+          android:id="@+id/action_container"
+          android:orientation="vertical"
+          android:layout_width="match_parent"
+          android:layout_height="wrap_content"
+          android:paddingBottom="4dp"
+          android:clipToPadding="false"/>
+  </android.support.v4.widget.NestedScrollView>
+</LinearLayout>
diff --git a/java/com/android/dialer/historyitemactions/res/values-land/styles.xml b/java/com/android/dialer/historyitemactions/res/values-land/styles.xml
new file mode 100644
index 0000000..bc727d0
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/values-land/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+  <style name="HistoryItemBottomSheet.BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
+    <item name="behavior_peekHeight">206dp</item>
+  </style>
+</resources>
diff --git a/java/com/android/dialer/historyitemactions/res/values/dimens.xml b/java/com/android/dialer/historyitemactions/res/values/dimens.xml
index 47bf804..a98101e 100644
--- a/java/com/android/dialer/historyitemactions/res/values/dimens.xml
+++ b/java/com/android/dialer/historyitemactions/res/values/dimens.xml
@@ -17,4 +17,5 @@
 <resources>
   <dimen name="contact_actions_image_size">48dp</dimen>
   <dimen name="contact_actions_image_margin">12dp</dimen>
+  <dimen name="contact_actions_header_elevation">4dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/java/com/android/dialer/historyitemactions/res/values/styles.xml b/java/com/android/dialer/historyitemactions/res/values/styles.xml
new file mode 100644
index 0000000..ed3cf11
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/values/styles.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+  <style name="HistoryItemBottomSheet.Base" parent="Theme.Design.Light.BottomSheetDialog">
+    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
+    <item name="android:windowTranslucentNavigation">false</item>
+    <item name="android:windowTranslucentStatus">false</item>
+    <item name="android:navigationBarColor">@color/background_dialer_white</item>
+  </style>
+
+  <style name="HistoryItemBottomSheet" parent="HistoryItemBottomSheet.Base">
+    <item name="bottomSheetStyle">@style/HistoryItemBottomSheet.BottomSheetStyle</item>
+  </style>
+
+  <style name="HistoryItemBottomSheet.BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
+    <item name="behavior_peekHeight">405dp</item>
+  </style>
+</resources>
diff --git a/java/com/android/dialer/inject/GenerateDaggerApp.java b/java/com/android/dialer/inject/GenerateDaggerApp.java
new file mode 100644
index 0000000..042561d
--- /dev/null
+++ b/java/com/android/dialer/inject/GenerateDaggerApp.java
@@ -0,0 +1,30 @@
+/*
+ * 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.inject;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/** Annotates an inner class where an application with dagger instance is needed. */
+@Target({ElementType.TYPE})
+public @interface GenerateDaggerApp {
+  /** Name of the application to be generated. */
+  String name();
+
+  /** Dialer variant of the application to be generated. */
+  DialerVariant variant();
+}
diff --git a/java/com/android/dialer/inject/RootComponentGeneratorMetadata.java b/java/com/android/dialer/inject/RootComponentGeneratorMetadata.java
index 51d134a..924b41e 100644
--- a/java/com/android/dialer/inject/RootComponentGeneratorMetadata.java
+++ b/java/com/android/dialer/inject/RootComponentGeneratorMetadata.java
@@ -20,8 +20,8 @@
 import java.lang.annotation.Target;
 
 /**
- * Only used by rootcomponent generator to store metadata for locating annotated
- * (@DialerComponent, @InstallIn) class.
+ * Only used by rootcomponent generator to store metadata for locating annotated class with {@link
+ * IncludeInDialerRoot}, {@link InstallIn}.
  */
 @Target(ElementType.TYPE)
 public @interface RootComponentGeneratorMetadata {
diff --git a/java/com/android/dialer/rootcomponentgenerator/DaggerApplicationGeneratingStep.java b/java/com/android/dialer/rootcomponentgenerator/DaggerApplicationGeneratingStep.java
new file mode 100644
index 0000000..7a23486
--- /dev/null
+++ b/java/com/android/dialer/rootcomponentgenerator/DaggerApplicationGeneratingStep.java
@@ -0,0 +1,146 @@
+/*
+ * 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.rootcomponentgenerator;
+
+import com.android.dialer.inject.DialerRootComponent;
+import com.android.dialer.inject.DialerVariant;
+import com.android.dialer.inject.GenerateDaggerApp;
+import com.android.dialer.inject.HasRootComponent;
+import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
+import com.google.auto.common.MoreElements;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.SetMultimap;
+import com.squareup.javapoet.AnnotationSpec;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import java.lang.annotation.Annotation;
+import java.util.Collections;
+import java.util.Set;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+
+/**
+ * Generates an application class with dagger component instance for a type annotated with {@link
+ * GenerateDaggerApp}.
+ *
+ * <p>Generated code example:
+ *
+ * <p><code>
+ *  @DialerRootComponent(variant = DialerVariant.DIALER_TEST)
+ * class GeneratedApplication extends Application implements HasRootComponent {
+ *  private volatile Object rootComponent;
+ *
+ *  @Override
+ *  @NonNull
+ *  public final Object component() {
+ *   Object result = rootComponent;
+ *     if (result == null) {
+ *       synchronized (this) {
+ *         result = rootComponent;
+ *         if (result == null) {
+ *           rootComponent =
+ *              result = DaggerDialerTest.builder().contextModule(new ContextModule(this)).build();
+ *         }
+ *       }
+ *     }
+ *   return result;
+ *  }
+ * }
+ * </code>
+ */
+public class DaggerApplicationGeneratingStep implements ProcessingStep {
+
+  private static final ClassName ANDROID_APPLICATION_CLASS_NAME =
+      ClassName.get("android.app", "Application");
+
+  private final ProcessingEnvironment processingEnv;
+
+  public DaggerApplicationGeneratingStep(ProcessingEnvironment processingEnv) {
+    this.processingEnv = processingEnv;
+  }
+
+  @Override
+  public Set<? extends Class<? extends Annotation>> annotations() {
+    return ImmutableSet.of(GenerateDaggerApp.class);
+  }
+
+  @Override
+  public Set<? extends Element> process(
+      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+    for (Element element : elementsByAnnotation.get(GenerateDaggerApp.class)) {
+      GenerateDaggerApp generateDaggerApp = element.getAnnotation(GenerateDaggerApp.class);
+      RootComponentUtils.writeJavaFile(
+          processingEnv,
+          ClassName.get(MoreElements.asType(element)).packageName(),
+          generateDaggerApplication(generateDaggerApp.name(), generateDaggerApp.variant()));
+    }
+
+    return Collections.emptySet();
+  }
+
+  private TypeSpec generateDaggerApplication(String name, DialerVariant variant) {
+    return TypeSpec.classBuilder(name)
+        .addAnnotation(
+            AnnotationSpec.builder(DialerRootComponent.class)
+                .addMember("variant", "$T.$L", DialerVariant.class, variant.name())
+                .build())
+        .superclass(ANDROID_APPLICATION_CLASS_NAME)
+        .addSuperinterface(HasRootComponent.class)
+        .addField(
+            FieldSpec.builder(TypeName.OBJECT, "rootComponent", Modifier.PRIVATE, Modifier.VOLATILE)
+                .build())
+        .addMethod(generateComponentMethod(variant))
+        .build();
+  }
+
+  private MethodSpec generateComponentMethod(DialerVariant dialerVariant) {
+    return MethodSpec.overriding(getComponentMethodFromHasRootComponent())
+        .addModifiers(Modifier.FINAL)
+        .addAnnotation(ClassName.get("android.support.annotation", "NonNull"))
+        .addStatement("$T result = rootComponent", TypeName.OBJECT)
+        .beginControlFlow("if (result == null)")
+        .beginControlFlow("synchronized (this)")
+        .addStatement("result = rootComponent")
+        .beginControlFlow("if (result == null)")
+        .addStatement(
+            "rootComponent = result = Dagger$L.builder().contextModule(new $T(this)).build()",
+            dialerVariant,
+            ClassName.get("com.android.dialer.inject", "ContextModule"))
+        .endControlFlow()
+        .endControlFlow()
+        .endControlFlow()
+        .addStatement("return result")
+        .build();
+  }
+
+  private ExecutableElement getComponentMethodFromHasRootComponent() {
+    TypeElement hasRootComponentInterafce =
+        processingEnv.getElementUtils().getTypeElement(HasRootComponent.class.getTypeName());
+    for (Element element : hasRootComponentInterafce.getEnclosedElements()) {
+      if (element.getSimpleName().contentEquals("component")) {
+        return MoreElements.asExecutable(element);
+      }
+    }
+    throw new RuntimeException("No component method inside HasRootComponent!");
+  }
+}
diff --git a/java/com/android/dialer/rootcomponentgenerator/RootComponentGeneratingStep.java b/java/com/android/dialer/rootcomponentgenerator/RootComponentGeneratingStep.java
index 4c4e6ee..cb31208 100644
--- a/java/com/android/dialer/rootcomponentgenerator/RootComponentGeneratingStep.java
+++ b/java/com/android/dialer/rootcomponentgenerator/RootComponentGeneratingStep.java
@@ -72,8 +72,7 @@
       // defer root components to the next round in case where the current build target contains
       // elements annotated with @InstallIn. Annotation processor cannot detect metadata files
       // generated in the same round and the metadata is accessible in the next round.
-      if (elementsByAnnotation.containsKey(InstallIn.class)
-          || elementsByAnnotation.containsKey(IncludeInDialerRoot.class)) {
+      if (shouldDeferRootComponent(elementsByAnnotation)) {
         return elementsByAnnotation.get(DialerRootComponent.class);
       } else {
         generateRootComponent(MoreElements.asType(element));
@@ -82,6 +81,12 @@
     return Collections.emptySet();
   }
 
+  private boolean shouldDeferRootComponent(
+      SetMultimap<Class<? extends Annotation>, Element> elementsByAnnotation) {
+    return elementsByAnnotation.containsKey(InstallIn.class)
+        || elementsByAnnotation.containsKey(IncludeInDialerRoot.class);
+  }
+
   /**
    * Generates a root component.
    *
diff --git a/java/com/android/dialer/rootcomponentgenerator/RootComponentProcessor.java b/java/com/android/dialer/rootcomponentgenerator/RootComponentProcessor.java
index 76df5e3..be043eb 100644
--- a/java/com/android/dialer/rootcomponentgenerator/RootComponentProcessor.java
+++ b/java/com/android/dialer/rootcomponentgenerator/RootComponentProcessor.java
@@ -30,6 +30,7 @@
   protected Iterable<? extends ProcessingStep> initSteps() {
     return ImmutableList.of(
         new MetadataGeneratingStep(processingEnv),
+        new DaggerApplicationGeneratingStep(processingEnv),
         new RootComponentGeneratingStep(processingEnv));
   }
 
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index 17591aa..c174599 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -80,7 +80,7 @@
 public class SpeedDialFragment extends Fragment {
 
   private final SpeedDialHeaderListener headerListener = new SpeedDialFragmentHeaderListener();
-  private final SuggestedContactsListener suggestedListener = new SpeedDialSuggestedListener();
+  private final SpeedDialSuggestedListener suggestedListener = new SpeedDialSuggestedListener();
 
   private ContextMenu contextMenu;
   private FrameLayout contextMenuBackground;
@@ -214,6 +214,7 @@
                 }),
         new DefaultFutureCallback<>(),
         DialerExecutorComponent.get(getContext()).backgroundExecutor());
+    suggestedListener.onPause();
   }
 
   @Override
@@ -313,6 +314,8 @@
 
   private final class SpeedDialSuggestedListener implements SuggestedContactsListener {
 
+    private HistoryItemActionBottomSheet bottomSheet;
+
     @Override
     public void onOverFlowMenuClicked(
         SpeedDialUiItem speedDialUiItem, HistoryItemBottomSheetHeaderInfo headerInfo) {
@@ -364,7 +367,7 @@
               R.string.contact_menu_contact_info,
               R.drawable.context_menu_contact_icon));
 
-      HistoryItemActionBottomSheet.show(getContext(), headerInfo, modules);
+      bottomSheet = HistoryItemActionBottomSheet.show(getContext(), headerInfo, modules);
     }
 
     @Override
@@ -430,6 +433,12 @@
         return false;
       }
     }
+
+    public void onPause() {
+      if (bottomSheet != null && bottomSheet.isShowing()) {
+        bottomSheet.dismiss();
+      }
+    }
   }
 
   private static final class SpeedDialContextMenuItemListener implements ContextMenuItemListener {