Loading java/com/android/incallui/answer/impl/AnswerFragment.java +33 −23 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; Loading Loading @@ -82,6 +84,8 @@ import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.maps.MapsComponent; import com.android.incallui.sessiondata.AvatarPresenter; import com.android.incallui.sessiondata.MultimediaFragment; import com.android.incallui.speakeasy.Annotations.SpeakEasyIcon; import com.android.incallui.speakeasy.Annotations.SpeakEasyText; import com.android.incallui.speakeasy.SpeakEasyComponent; import com.android.incallui.util.AccessibilityUtil; import com.android.incallui.video.protocol.VideoCallScreen; Loading Loading @@ -144,6 +148,9 @@ public class AnswerFragment extends Fragment private View importanceBadge; private SwipeButtonView secondaryButton; private SwipeButtonView answerAndReleaseButton; private LinearLayout chipLayout; private ImageView chipIcon; private TextView chipText; private AffordanceHolderLayout affordanceHolderLayout; // Use these flags to prevent user from clicking accept/reject buttons multiple times. // We use separate flags because in some rare cases accepting a call may fail to join the room, Loading Loading @@ -195,17 +202,6 @@ public class AnswerFragment extends Fragment public void performAction(AnswerFragment fragment) { fragment.performAnswerAndRelease(); } }, SPEAKEASY( R.drawable.quantum_ic_rtt_vd_theme_24, R.string.speakeasy_secondary_button_hint, R.string.speakeasy_secondary_button_hint, R.string.speakeasy_secondary_button_hint) { @Override public void performAction(AnswerFragment fragment) { fragment.performSpeakEasy(); } }; @DrawableRes public int icon; Loading @@ -232,8 +228,7 @@ public class AnswerFragment extends Fragment } } private void performSpeakEasy() { restoreAnswerAndReleaseButtonAnimation(); private void performSpeakEasy(View unused) { answerScreenDelegate.onSpeakEasyCall(); buttonAcceptClicked = true; } Loading Loading @@ -457,16 +452,6 @@ public class AnswerFragment extends Fragment if (allowAnswerAndRelease()) { answerAndReleaseButton.setVisibility(View.VISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonEnabled(); } else if (allowSpeakEasy()) { Optional<Integer> alternativeIcon = SpeakEasyComponent.get(getContext()).speakEasyIcon(); if (alternativeIcon.isPresent()) { // TODO(erfanian): Replace enum hack when we have a dedicated button. SecondaryBehavior.SPEAKEASY.icon = alternativeIcon.get(); } answerAndReleaseBehavior = SecondaryBehavior.SPEAKEASY; answerAndReleaseBehavior.applyToView(answerAndReleaseButton); answerAndReleaseButton.setVisibility(View.VISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonEnabled(); } else { answerAndReleaseButton.setVisibility(View.INVISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonDisabled(); Loading @@ -480,6 +465,27 @@ public class AnswerFragment extends Fragment }); } /** Initialize chip buttons */ private void initChips() { if (!allowSpeakEasy()) { chipLayout.setVisibility(View.GONE); return; } chipLayout.setVisibility(View.VISIBLE); chipLayout.setOnClickListener(this::performSpeakEasy); @SpeakEasyIcon Optional<Integer> alternativeIcon = SpeakEasyComponent.get(getContext()).speakEasyIcon(); @SpeakEasyText Optional<Integer> alternativeText = SpeakEasyComponent.get(getContext()).speakEasyText(); if (alternativeIcon.isPresent() && alternativeText.isPresent()) { chipIcon.setImageDrawable(getContext().getDrawable(alternativeIcon.get())); chipText.setText(alternativeText.get()); // The button needs to override normal swipe up/down behavior. chipLayout.bringToFront(); } } @Override public boolean allowAnswerAndRelease() { return getArguments().getBoolean(ARG_ALLOW_ANSWER_AND_RELEASE); Loading Loading @@ -715,6 +721,9 @@ public class AnswerFragment extends Fragment View view = inflater.inflate(R.layout.fragment_incoming_call, container, false); secondaryButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button); answerAndReleaseButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button2); chipLayout = view.findViewById(R.id.incall_data_container_chip_container); chipIcon = view.findViewById(R.id.incall_data_container_chip_icon); chipText = view.findViewById(R.id.incall_data_container_chip_text); affordanceHolderLayout = (AffordanceHolderLayout) view.findViewById(R.id.incoming_container); affordanceHolderLayout.setAffordanceCallback(affordanceCallback); Loading Loading @@ -755,6 +764,7 @@ public class AnswerFragment extends Fragment .newAnswerScreenDelegate(this); initSecondaryButton(); initChips(); int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; if (!isInMultiWindowMode Loading java/com/android/incallui/answer/impl/res/drawable/shape_chip_drawable.xml 0 → 100644 +44 −0 Original line number Diff line number Diff line <?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 --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#DADCE0"> <item android:id="@android:id/mask"> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/dialer_background_light"/> <padding android:bottom="9dp" android:left="8dp" android:right="8dp" android:top="9dp"/> <corners android:radius="40dp"/> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/dialer_background_floating_light"/> <stroke android:width="1dp" android:color="#DADCE0"/> <padding android:bottom="9dp" android:left="8dp" android:right="8dp" android:top="9dp"/> <corners android:radius="40dp"/> </shape> </item> </ripple> No newline at end of file java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml +40 −14 Original line number Diff line number Diff line Loading @@ -53,6 +53,13 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@+id/answer_method_container" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"/> <TextView android:id="@+id/videocall_video_off" android:layout_width="wrap_content" Loading @@ -74,8 +81,8 @@ android:layout_marginTop="24dp" android:clipChildren="false" android:clipToPadding="false" android:gravity="top|center_horizontal" android:focusable="true" android:gravity="top|center_horizontal" android:orientation="vertical"> <include Loading Loading @@ -114,19 +121,19 @@ <!-- TODO(a bug): textColorPrimary or textColorPrimaryInverse? --> <TextView android:id="@+id/incall_important_call_badge" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="48dp" android:layout_marginTop="4dp" android:layout_marginBottom="@dimen/answer_importance_margin_bottom" android:gravity="center" android:background="@drawable/urgent_call_background" android:elevation="@dimen/answer_data_elevation" android:gravity="center" android:maxLines="1" android:text="@string/call_incoming_important" android:textAllCaps="true" android:textSize="14sp" android:textStyle="bold" android:textColor="?android:attr/colorBackground" android:background="@drawable/urgent_call_background"/> android:textSize="14sp"/> <FrameLayout android:id="@+id/incall_location_holder" Loading @@ -144,7 +151,34 @@ android:layout_height="0dp" android:layout_weight="1" android:clipChildren="false" android:clipToPadding="false"/> android:clipToPadding="false"> <LinearLayout android:id="@+id/incall_data_container_chip_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:background="@drawable/shape_chip_drawable" android:clickable="true" android:orientation="horizontal" android:visibility="gone"> <ImageView android:id="@+id/incall_data_container_chip_icon" android:layout_width="20dp" android:layout_height="20dp" android:src="@drawable/quantum_ic_rtt_vd_theme_24" android:tint="#1A73E8"/> <TextView android:id="@+id/incall_data_container_chip_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:fontFamily="sans-serif-medium" android:text="@string/speakeasy_secondary_button_hint" android:textColor="@color/dialer_primary_text_color" android:textSize="14sp"/> </LinearLayout> </FrameLayout> <!-- Space holder for answer method. This is used to get better scaling to make room for incall_data_container on different screen size. --> Loading @@ -153,14 +187,6 @@ android:layout_height="220dp"/> </LinearLayout> <FrameLayout android:id="@+id/answer_method_container" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"/> </FrameLayout> <com.android.incallui.answer.impl.affordance.SwipeButtonView Loading java/com/android/incallui/speakeasy/Annotations.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * 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.incallui.speakeasy; import javax.inject.Qualifier; /** Annotations for Speakeasy providers. */ public final class Annotations { /** A Speakeasy icon */ @Qualifier public @interface SpeakEasyIcon {} /** Speakeasy text */ @Qualifier public @interface SpeakEasyText {} /** A Speakeasy settings fragment */ @Qualifier public @interface SpeakEasySettingsFragment {} } java/com/android/incallui/speakeasy/SpeakEasyComponent.java +7 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.incallui.speakeasy; import android.content.Context; import android.support.v4.app.Fragment; import com.android.dialer.inject.HasRootComponent; import com.android.incallui.speakeasy.Annotations.SpeakEasyIcon; import com.android.incallui.speakeasy.Annotations.SpeakEasySettingsFragment; import com.android.incallui.speakeasy.Annotations.SpeakEasyText; import com.google.common.base.Optional; import dagger.Subcomponent; Loading @@ -28,9 +31,11 @@ public abstract class SpeakEasyComponent { public abstract SpeakEasyCallManager speakEasyCallManager(); public abstract Optional<Fragment> speakEasySettingsFragment(); public abstract @SpeakEasySettingsFragment Optional<Fragment> speakEasySettingsFragment(); public abstract Optional<Integer> speakEasyIcon(); public abstract @SpeakEasyIcon Optional<Integer> speakEasyIcon(); public abstract @SpeakEasyText Optional<Integer> speakEasyText(); public static SpeakEasyComponent get(Context context) { return ((SpeakEasyComponent.HasComponent) Loading Loading
java/com/android/incallui/answer/impl/AnswerFragment.java +33 −23 Original line number Diff line number Diff line Loading @@ -49,6 +49,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; Loading Loading @@ -82,6 +84,8 @@ import com.android.incallui.incalluilock.InCallUiLock; import com.android.incallui.maps.MapsComponent; import com.android.incallui.sessiondata.AvatarPresenter; import com.android.incallui.sessiondata.MultimediaFragment; import com.android.incallui.speakeasy.Annotations.SpeakEasyIcon; import com.android.incallui.speakeasy.Annotations.SpeakEasyText; import com.android.incallui.speakeasy.SpeakEasyComponent; import com.android.incallui.util.AccessibilityUtil; import com.android.incallui.video.protocol.VideoCallScreen; Loading Loading @@ -144,6 +148,9 @@ public class AnswerFragment extends Fragment private View importanceBadge; private SwipeButtonView secondaryButton; private SwipeButtonView answerAndReleaseButton; private LinearLayout chipLayout; private ImageView chipIcon; private TextView chipText; private AffordanceHolderLayout affordanceHolderLayout; // Use these flags to prevent user from clicking accept/reject buttons multiple times. // We use separate flags because in some rare cases accepting a call may fail to join the room, Loading Loading @@ -195,17 +202,6 @@ public class AnswerFragment extends Fragment public void performAction(AnswerFragment fragment) { fragment.performAnswerAndRelease(); } }, SPEAKEASY( R.drawable.quantum_ic_rtt_vd_theme_24, R.string.speakeasy_secondary_button_hint, R.string.speakeasy_secondary_button_hint, R.string.speakeasy_secondary_button_hint) { @Override public void performAction(AnswerFragment fragment) { fragment.performSpeakEasy(); } }; @DrawableRes public int icon; Loading @@ -232,8 +228,7 @@ public class AnswerFragment extends Fragment } } private void performSpeakEasy() { restoreAnswerAndReleaseButtonAnimation(); private void performSpeakEasy(View unused) { answerScreenDelegate.onSpeakEasyCall(); buttonAcceptClicked = true; } Loading Loading @@ -457,16 +452,6 @@ public class AnswerFragment extends Fragment if (allowAnswerAndRelease()) { answerAndReleaseButton.setVisibility(View.VISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonEnabled(); } else if (allowSpeakEasy()) { Optional<Integer> alternativeIcon = SpeakEasyComponent.get(getContext()).speakEasyIcon(); if (alternativeIcon.isPresent()) { // TODO(erfanian): Replace enum hack when we have a dedicated button. SecondaryBehavior.SPEAKEASY.icon = alternativeIcon.get(); } answerAndReleaseBehavior = SecondaryBehavior.SPEAKEASY; answerAndReleaseBehavior.applyToView(answerAndReleaseButton); answerAndReleaseButton.setVisibility(View.VISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonEnabled(); } else { answerAndReleaseButton.setVisibility(View.INVISIBLE); answerScreenDelegate.onAnswerAndReleaseButtonDisabled(); Loading @@ -480,6 +465,27 @@ public class AnswerFragment extends Fragment }); } /** Initialize chip buttons */ private void initChips() { if (!allowSpeakEasy()) { chipLayout.setVisibility(View.GONE); return; } chipLayout.setVisibility(View.VISIBLE); chipLayout.setOnClickListener(this::performSpeakEasy); @SpeakEasyIcon Optional<Integer> alternativeIcon = SpeakEasyComponent.get(getContext()).speakEasyIcon(); @SpeakEasyText Optional<Integer> alternativeText = SpeakEasyComponent.get(getContext()).speakEasyText(); if (alternativeIcon.isPresent() && alternativeText.isPresent()) { chipIcon.setImageDrawable(getContext().getDrawable(alternativeIcon.get())); chipText.setText(alternativeText.get()); // The button needs to override normal swipe up/down behavior. chipLayout.bringToFront(); } } @Override public boolean allowAnswerAndRelease() { return getArguments().getBoolean(ARG_ALLOW_ANSWER_AND_RELEASE); Loading Loading @@ -715,6 +721,9 @@ public class AnswerFragment extends Fragment View view = inflater.inflate(R.layout.fragment_incoming_call, container, false); secondaryButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button); answerAndReleaseButton = (SwipeButtonView) view.findViewById(R.id.incoming_secondary_button2); chipLayout = view.findViewById(R.id.incall_data_container_chip_container); chipIcon = view.findViewById(R.id.incall_data_container_chip_icon); chipText = view.findViewById(R.id.incall_data_container_chip_text); affordanceHolderLayout = (AffordanceHolderLayout) view.findViewById(R.id.incoming_container); affordanceHolderLayout.setAffordanceCallback(affordanceCallback); Loading Loading @@ -755,6 +764,7 @@ public class AnswerFragment extends Fragment .newAnswerScreenDelegate(this); initSecondaryButton(); initChips(); int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; if (!isInMultiWindowMode Loading
java/com/android/incallui/answer/impl/res/drawable/shape_chip_drawable.xml 0 → 100644 +44 −0 Original line number Diff line number Diff line <?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 --> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#DADCE0"> <item android:id="@android:id/mask"> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/dialer_background_light"/> <padding android:bottom="9dp" android:left="8dp" android:right="8dp" android:top="9dp"/> <corners android:radius="40dp"/> </shape> </item> <item> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/dialer_background_floating_light"/> <stroke android:width="1dp" android:color="#DADCE0"/> <padding android:bottom="9dp" android:left="8dp" android:right="8dp" android:top="9dp"/> <corners android:radius="40dp"/> </shape> </item> </ripple> No newline at end of file
java/com/android/incallui/answer/impl/res/layout/fragment_incoming_call.xml +40 −14 Original line number Diff line number Diff line Loading @@ -53,6 +53,13 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> <FrameLayout android:id="@+id/answer_method_container" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"/> <TextView android:id="@+id/videocall_video_off" android:layout_width="wrap_content" Loading @@ -74,8 +81,8 @@ android:layout_marginTop="24dp" android:clipChildren="false" android:clipToPadding="false" android:gravity="top|center_horizontal" android:focusable="true" android:gravity="top|center_horizontal" android:orientation="vertical"> <include Loading Loading @@ -114,19 +121,19 @@ <!-- TODO(a bug): textColorPrimary or textColorPrimaryInverse? --> <TextView android:id="@+id/incall_important_call_badge" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="48dp" android:layout_marginTop="4dp" android:layout_marginBottom="@dimen/answer_importance_margin_bottom" android:gravity="center" android:background="@drawable/urgent_call_background" android:elevation="@dimen/answer_data_elevation" android:gravity="center" android:maxLines="1" android:text="@string/call_incoming_important" android:textAllCaps="true" android:textSize="14sp" android:textStyle="bold" android:textColor="?android:attr/colorBackground" android:background="@drawable/urgent_call_background"/> android:textSize="14sp"/> <FrameLayout android:id="@+id/incall_location_holder" Loading @@ -144,7 +151,34 @@ android:layout_height="0dp" android:layout_weight="1" android:clipChildren="false" android:clipToPadding="false"/> android:clipToPadding="false"> <LinearLayout android:id="@+id/incall_data_container_chip_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal|bottom" android:background="@drawable/shape_chip_drawable" android:clickable="true" android:orientation="horizontal" android:visibility="gone"> <ImageView android:id="@+id/incall_data_container_chip_icon" android:layout_width="20dp" android:layout_height="20dp" android:src="@drawable/quantum_ic_rtt_vd_theme_24" android:tint="#1A73E8"/> <TextView android:id="@+id/incall_data_container_chip_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:fontFamily="sans-serif-medium" android:text="@string/speakeasy_secondary_button_hint" android:textColor="@color/dialer_primary_text_color" android:textSize="14sp"/> </LinearLayout> </FrameLayout> <!-- Space holder for answer method. This is used to get better scaling to make room for incall_data_container on different screen size. --> Loading @@ -153,14 +187,6 @@ android:layout_height="220dp"/> </LinearLayout> <FrameLayout android:id="@+id/answer_method_container" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"/> </FrameLayout> <com.android.incallui.answer.impl.affordance.SwipeButtonView Loading
java/com/android/incallui/speakeasy/Annotations.java 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * 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.incallui.speakeasy; import javax.inject.Qualifier; /** Annotations for Speakeasy providers. */ public final class Annotations { /** A Speakeasy icon */ @Qualifier public @interface SpeakEasyIcon {} /** Speakeasy text */ @Qualifier public @interface SpeakEasyText {} /** A Speakeasy settings fragment */ @Qualifier public @interface SpeakEasySettingsFragment {} }
java/com/android/incallui/speakeasy/SpeakEasyComponent.java +7 −2 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package com.android.incallui.speakeasy; import android.content.Context; import android.support.v4.app.Fragment; import com.android.dialer.inject.HasRootComponent; import com.android.incallui.speakeasy.Annotations.SpeakEasyIcon; import com.android.incallui.speakeasy.Annotations.SpeakEasySettingsFragment; import com.android.incallui.speakeasy.Annotations.SpeakEasyText; import com.google.common.base.Optional; import dagger.Subcomponent; Loading @@ -28,9 +31,11 @@ public abstract class SpeakEasyComponent { public abstract SpeakEasyCallManager speakEasyCallManager(); public abstract Optional<Fragment> speakEasySettingsFragment(); public abstract @SpeakEasySettingsFragment Optional<Fragment> speakEasySettingsFragment(); public abstract Optional<Integer> speakEasyIcon(); public abstract @SpeakEasyIcon Optional<Integer> speakEasyIcon(); public abstract @SpeakEasyText Optional<Integer> speakEasyText(); public static SpeakEasyComponent get(Context context) { return ((SpeakEasyComponent.HasComponent) Loading