From 22ff338e7383592443da291587442deb5f4e6758 Mon Sep 17 00:00:00 2001 From: mdooley Date: Thu, 16 Nov 2017 21:25:00 -0800 Subject: Don't transcribe voicemail unless carrier allows OTT transcription Added a carrier config and check to see if the carrier allows over the top voicemail transcription, and if not do not attempt transcription. Bug: 68951869 Test: manual and unit test PiperOrigin-RevId: 176065849 Change-Id: I69df1f2867420d7fdcc7f0a31e0e6c26da67abb1 --- .../error/VoicemailTosMessageCreator.java | 7 ++- java/com/android/voicemail/CarrierConfigKeys.java | 31 ++++++++++ java/com/android/voicemail/VoicemailClient.java | 9 ++- .../voicemail/impl/VoicemailClientImpl.java | 12 +++- .../android/voicemail/impl/res/xml/vvm_config.xml | 1 + .../transcribe/TranscriptionBackfillService.java | 9 ++- .../impl/transcribe/TranscriptionService.java | 66 +++++++++++++--------- .../voicemail/stub/StubVoicemailClient.java | 8 ++- 8 files changed, 109 insertions(+), 34 deletions(-) create mode 100644 java/com/android/voicemail/CarrierConfigKeys.java diff --git a/java/com/android/dialer/app/voicemail/error/VoicemailTosMessageCreator.java b/java/com/android/dialer/app/voicemail/error/VoicemailTosMessageCreator.java index 1092175ae..3e4321309 100644 --- a/java/com/android/dialer/app/voicemail/error/VoicemailTosMessageCreator.java +++ b/java/com/android/dialer/app/voicemail/error/VoicemailTosMessageCreator.java @@ -347,7 +347,12 @@ public class VoicemailTosMessageCreator { .putInt(PREF_DIALER_TOS_VERSION_ACCEPTED_KEY, CURRENT_DIALER_TOS_VERSION) .apply(); } - VoicemailComponent.get(context).getVoicemailClient().onTosAccepted(context); + + PhoneAccountHandle handle = + new PhoneAccountHandle( + ComponentName.unflattenFromString(status.phoneAccountComponentName), + status.phoneAccountId); + VoicemailComponent.get(context).getVoicemailClient().onTosAccepted(context, handle); } private boolean hasAcknowledgedFeatures() { diff --git a/java/com/android/voicemail/CarrierConfigKeys.java b/java/com/android/voicemail/CarrierConfigKeys.java new file mode 100644 index 000000000..609221d0f --- /dev/null +++ b/java/com/android/voicemail/CarrierConfigKeys.java @@ -0,0 +1,31 @@ +/* + * 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.voicemail; + +/** + * Keys used to lookup carrier specific configuration strings. See {@code + * VoicemailClient.getCarrierConfigString} + */ +public interface CarrierConfigKeys { + + /** + * Carrier config key whose value will be 'true' for carriers that allow over the top voicemail + * transcription. + */ + String VVM_CARRIER_ALLOWS_OTT_TRANSCRIPTION_STRING = + "vvm_carrier_allows_ott_transcription_string"; +} diff --git a/java/com/android/voicemail/VoicemailClient.java b/java/com/android/voicemail/VoicemailClient.java index 050286a41..db5d74555 100644 --- a/java/com/android/voicemail/VoicemailClient.java +++ b/java/com/android/voicemail/VoicemailClient.java @@ -177,5 +177,12 @@ public interface VoicemailClient { /** Provides interface to change the PIN used to access the mailbox by calling. */ PinChanger createPinChanger(Context context, PhoneAccountHandle phoneAccountHandle); - void onTosAccepted(Context context); + void onTosAccepted(Context context, PhoneAccountHandle phoneAccountHandle); + + /** + * @return arbitrary carrier configuration String value associate with the indicated key. See + * {@code CarrierConfigKeys.java} + */ + @Nullable + String getCarrierConfigString(Context context, PhoneAccountHandle phoneAccountHandle, String key); } diff --git a/java/com/android/voicemail/impl/VoicemailClientImpl.java b/java/com/android/voicemail/impl/VoicemailClientImpl.java index 2add59ec7..330543837 100644 --- a/java/com/android/voicemail/impl/VoicemailClientImpl.java +++ b/java/com/android/voicemail/impl/VoicemailClientImpl.java @@ -22,6 +22,7 @@ import android.provider.VoicemailContract.Status; import android.provider.VoicemailContract.Voicemails; import android.support.annotation.MainThread; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.os.BuildCompat; import android.telecom.PhoneAccountHandle; import android.telephony.TelephonyManager; @@ -285,8 +286,15 @@ public class VoicemailClientImpl implements VoicemailClient { } @Override - public void onTosAccepted(Context context) { + public void onTosAccepted(Context context, PhoneAccountHandle account) { LogUtil.i("VoicemailClientImpl.onTosAccepted", "try backfilling voicemail transcriptions"); - TranscriptionBackfillService.scheduleTask(context); + TranscriptionBackfillService.scheduleTask(context, account); + } + + @Override + @Nullable + public String getCarrierConfigString(Context context, PhoneAccountHandle account, String key) { + OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, account); + return helper.isValid() ? helper.getString(key) : null; } } diff --git a/java/com/android/voicemail/impl/res/xml/vvm_config.xml b/java/com/android/voicemail/impl/res/xml/vvm_config.xml index 1e5190a7c..499bae293 100644 --- a/java/com/android/voicemail/impl/res/xml/vvm_config.xml +++ b/java/com/android/voicemail/impl/res/xml/vvm_config.xml @@ -104,6 +104,7 @@ + true diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java index f7f643932..8161e71f7 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionBackfillService.java @@ -25,6 +25,7 @@ import android.net.Uri; import android.support.annotation.WorkerThread; import android.support.v4.app.JobIntentService; import android.support.v4.os.BuildCompat; +import android.telecom.PhoneAccountHandle; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.constants.ScheduledJobIds; @@ -38,7 +39,7 @@ import java.util.List; public class TranscriptionBackfillService extends JobIntentService { /** Schedule a task to scan the database for untranscribed voicemails */ - public static boolean scheduleTask(Context context) { + public static boolean scheduleTask(Context context, PhoneAccountHandle account) { if (BuildCompat.isAtLeastO()) { LogUtil.enterBlock("TranscriptionBackfillService.transcribeOldVoicemails"); ComponentName componentName = new ComponentName(context, TranscriptionBackfillService.class); @@ -46,15 +47,17 @@ public class TranscriptionBackfillService extends JobIntentService { new JobInfo.Builder(ScheduledJobIds.VVM_TRANSCRIPTION_BACKFILL_JOB, componentName) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); JobScheduler scheduler = context.getSystemService(JobScheduler.class); - return scheduler.enqueue(builder.build(), makeWorkItem()) == JobScheduler.RESULT_SUCCESS; + return scheduler.enqueue(builder.build(), makeWorkItem(account)) + == JobScheduler.RESULT_SUCCESS; } else { LogUtil.i("TranscriptionBackfillService.transcribeOldVoicemails", "not supported"); return false; } } - private static JobWorkItem makeWorkItem() { + private static JobWorkItem makeWorkItem(PhoneAccountHandle account) { Intent intent = new Intent(); + intent.putExtra(TranscriptionService.EXTRA_ACCOUNT_HANDLE, account); return new JobWorkItem(intent); } diff --git a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java index 79e1a017c..33c9676a4 100644 --- a/java/com/android/voicemail/impl/transcribe/TranscriptionService.java +++ b/java/com/android/voicemail/impl/transcribe/TranscriptionService.java @@ -24,10 +24,9 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.support.annotation.MainThread; -import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; -import android.support.v4.os.BuildCompat; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import com.android.dialer.common.Assert; @@ -35,6 +34,9 @@ import com.android.dialer.common.LogUtil; import com.android.dialer.constants.ScheduledJobIds; import com.android.dialer.logging.DialerImpression; import com.android.dialer.logging.Logger; +import com.android.voicemail.CarrierConfigKeys; +import com.android.voicemail.VoicemailClient; +import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.transcribe.grpc.TranscriptionClientFactory; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -65,34 +67,46 @@ public class TranscriptionService extends JobService { // donation. @MainThread public static boolean scheduleNewVoicemailTranscriptionJob( - Context context, - Uri voicemailUri, - @Nullable PhoneAccountHandle account, - boolean highPriority) { + Context context, Uri voicemailUri, PhoneAccountHandle account, boolean highPriority) { Assert.isMainThread(); - if (BuildCompat.isAtLeastO()) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { LogUtil.i( - "TranscriptionService.scheduleNewVoicemailTranscriptionJob", "scheduling transcription"); - Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_VOICEMAIL_RECEIVED); - - ComponentName componentName = new ComponentName(context, TranscriptionService.class); - JobInfo.Builder builder = - new JobInfo.Builder(ScheduledJobIds.VVM_TRANSCRIPTION_JOB, componentName); - if (highPriority) { - builder - .setMinimumLatency(0) - .setOverrideDeadline(0) - .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); - } else { - builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); - } - JobScheduler scheduler = context.getSystemService(JobScheduler.class); - JobWorkItem workItem = makeWorkItem(voicemailUri, account); - return scheduler.enqueue(builder.build(), workItem) == JobScheduler.RESULT_SUCCESS; - } else { - LogUtil.i("TranscriptionService.scheduleNewVoicemailTranscriptionJob", "not supported"); + "TranscriptionService.scheduleNewVoicemailTranscriptionJob", "not supported by sdk"); return false; } + if (!carrierAllowsOttTranscription(context, account)) { + LogUtil.i( + "TranscriptionService.scheduleNewVoicemailTranscriptionJob", + "carrier doesn't allow transcription"); + return false; + } + + LogUtil.i( + "TranscriptionService.scheduleNewVoicemailTranscriptionJob", "scheduling transcription"); + Logger.get(context).logImpression(DialerImpression.Type.VVM_TRANSCRIPTION_VOICEMAIL_RECEIVED); + + ComponentName componentName = new ComponentName(context, TranscriptionService.class); + JobInfo.Builder builder = + new JobInfo.Builder(ScheduledJobIds.VVM_TRANSCRIPTION_JOB, componentName); + if (highPriority) { + builder + .setMinimumLatency(0) + .setOverrideDeadline(0) + .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); + } else { + builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); + } + JobScheduler scheduler = context.getSystemService(JobScheduler.class); + JobWorkItem workItem = makeWorkItem(voicemailUri, account); + return scheduler.enqueue(builder.build(), workItem) == JobScheduler.RESULT_SUCCESS; + } + + private static boolean carrierAllowsOttTranscription( + Context context, PhoneAccountHandle account) { + VoicemailClient client = VoicemailComponent.get(context).getVoicemailClient(); + return Boolean.parseBoolean( + client.getCarrierConfigString( + context, account, CarrierConfigKeys.VVM_CARRIER_ALLOWS_OTT_TRANSCRIPTION_STRING)); } // Cancel all transcription tasks diff --git a/java/com/android/voicemail/stub/StubVoicemailClient.java b/java/com/android/voicemail/stub/StubVoicemailClient.java index fe063245f..cfbb3ec00 100644 --- a/java/com/android/voicemail/stub/StubVoicemailClient.java +++ b/java/com/android/voicemail/stub/StubVoicemailClient.java @@ -130,5 +130,11 @@ public final class StubVoicemailClient implements VoicemailClient { } @Override - public void onTosAccepted(Context context) {} + public void onTosAccepted(Context context, PhoneAccountHandle account) {} + + @Override + @Nullable + public String getCarrierConfigString(Context context, PhoneAccountHandle account, String key) { + return null; + } } -- cgit v1.2.3 From 038b4eedce750f09d0b12fd379137e4e618ca184 Mon Sep 17 00:00:00 2001 From: linyuh Date: Fri, 17 Nov 2017 10:01:59 -0800 Subject: Use OnPreDrawListener to adjust key layouts on the dialpad. Test: DialpadFragmentIntegrationTest PiperOrigin-RevId: 176122540 Change-Id: Iebf5ab67569fd4532411cfdae20ad5fb91cbcc55 --- .../android/dialer/dialpadview/DialpadView.java | 278 +++++++++++++++------ 1 file changed, 195 insertions(+), 83 deletions(-) diff --git a/java/com/android/dialer/dialpadview/DialpadView.java b/java/com/android/dialer/dialpadview/DialpadView.java index 73abd1274..4cbf42f2e 100644 --- a/java/com/android/dialer/dialpadview/DialpadView.java +++ b/java/com/android/dialer/dialpadview/DialpadView.java @@ -33,7 +33,9 @@ import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.view.ViewPropertyAnimator; +import android.view.ViewTreeObserver.OnPreDrawListener; import android.view.accessibility.AccessibilityManager; import android.widget.EditText; import android.widget.ImageButton; @@ -76,6 +78,7 @@ public class DialpadView extends LinearLayout { private final AttributeSet mAttributeSet; private final ColorStateList mRippleColor; + private final OnPreDrawListenerForKeyLayoutAdjust mOnPreDrawListenerForKeyLayoutAdjust; private final String[] mPrimaryLettersMapping; private final String[] mSecondaryLettersMapping; private final boolean mIsRtl; // whether the dialpad is shown in a right-to-left locale @@ -112,6 +115,21 @@ public class DialpadView extends LinearLayout { mPrimaryLettersMapping = DialpadCharMappings.getDefaultKeyToCharsMap(); mSecondaryLettersMapping = DialpadCharMappings.getKeyToCharsMap(context); + + mOnPreDrawListenerForKeyLayoutAdjust = new OnPreDrawListenerForKeyLayoutAdjust(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + getViewTreeObserver().removeOnPreDrawListener(mOnPreDrawListenerForKeyLayoutAdjust); + getViewTreeObserver().addOnPreDrawListener(mOnPreDrawListenerForKeyLayoutAdjust); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + getViewTreeObserver().removeOnPreDrawListener(mOnPreDrawListenerForKeyLayoutAdjust); } @Override @@ -221,89 +239,6 @@ public class DialpadView extends LinearLayout { zero.setLongHoverContentDescription(resources.getText(R.string.description_image_button_plus)); } - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - - if (changed) { - if (isLandscapeMode()) { - adjustKeyWidths(); - } else { - adjustDigitKeyHeights(); - } - } - } - - /** - * Make the heights of all digit keys the same. - * - *

When the device is in portrait mode, we first find the maximum height among digit key - * layouts. Then for each key, we adjust the height of the layout containing letters/the voice - * mail icon to ensure the height of each digit key is the same. - * - *

This method should be called after the sizes of related layouts have been calculated by the - * framework. - */ - private void adjustDigitKeyHeights() { - Assert.checkState(!isLandscapeMode()); - - int maxHeight = 0; - for (int i = 0; i <= 9; i++) { - DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); - LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); - maxHeight = Math.max(maxHeight, keyLayout.getHeight()); - } - - for (int i = 0; i <= 9; i++) { - DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); - LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); - - DialpadTextView numberView = - (DialpadTextView) keyLayout.findViewById(R.id.dialpad_key_number); - MarginLayoutParams numberViewLayoutParams = (MarginLayoutParams) numberView.getLayoutParams(); - - LinearLayout iconOrLettersLayout = - (LinearLayout) keyLayout.findViewById(R.id.dialpad_key_icon_or_letters_layout); - iconOrLettersLayout.setLayoutParams( - new LayoutParams( - LayoutParams.WRAP_CONTENT /* width */, - maxHeight - - numberView.getHeight() - - numberViewLayoutParams.topMargin - - numberViewLayoutParams.bottomMargin /* height */)); - } - } - - /** - * Make the widths of all keys the same. - * - *

When the device is in landscape mode, we first find the maximum width among key layouts. - * Then we adjust the width of each layout's horizontal placeholder so that each key has the same - * width. - * - *

This method should be called after the sizes of related layouts have been calculated by the - * framework. - */ - private void adjustKeyWidths() { - Assert.checkState(isLandscapeMode()); - - int maxWidth = 0; - for (int buttonId : BUTTON_IDS) { - DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId); - LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); - maxWidth = Math.max(maxWidth, keyLayout.getWidth()); - } - - for (int buttonId : BUTTON_IDS) { - DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId); - LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); - View horizontalPlaceholder = keyLayout.findViewById(R.id.dialpad_key_horizontal_placeholder); - horizontalPlaceholder.setLayoutParams( - new LayoutParams( - maxWidth - keyLayout.getWidth() /* width */, LayoutParams.MATCH_PARENT /* height */)); - } - } - private Drawable getDrawableCompat(Context context, int id) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { return context.getDrawable(id); @@ -559,4 +494,181 @@ public class DialpadView extends LinearLayout { private boolean isLandscapeMode() { return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; } + + /** + * An {@link OnPreDrawListener} that adjusts the height/width of each key layout so that they can + * be properly aligned. + * + *

When the device is in portrait mode, the layout height for key "1" can be different from + * those of other digit keys due to the voicemail icon. Adjustments are needed to ensure + * the layouts for all digit keys are of the same height. Key "*" and key "#" are excluded + * because their styles are different from other keys'. + * + *

When the device is in landscape mode, keys can have different layout widths due to the + * icon/characters associated with them. Adjustments are needed to ensure the layouts for all keys + * are of the same width. + * + *

Note that adjustments can only be made after the layouts are measured, which is why the + * logic lives in an {@link OnPreDrawListener} that is invoked when the view tree is about to be + * drawn. + */ + private class OnPreDrawListenerForKeyLayoutAdjust implements OnPreDrawListener { + + /** + * This method is invoked when the view tree is about to be drawn. At this point, all views in + * the tree have been measured and given a frame. + * + *

If the keys have been adjusted, we instruct the current drawing pass to proceed by + * returning true. Otherwise, adjustments will be made and the current drawing pass will be + * cancelled by returning false. + * + *

It is imperative to schedule another layout pass of the view tree after adjustments are + * made so that {@link #onPreDraw()} can be invoked again to check the layouts and proceed with + * the drawing pass. + */ + @Override + public boolean onPreDraw() { + if (!shouldAdjustKeySizes()) { + return true; // Return true to proceed with the current drawing pass. + } + + adjustKeySizes(); + return false; // Return false to cancel the current drawing pass. + } + + private boolean shouldAdjustKeySizes() { + return isLandscapeMode() ? shouldAdjustKeyWidths() : shouldAdjustDigitKeyHeights(); + } + + /** + * Return true if not all key layouts have the same width. This method must be called when the + * device is in landscape mode. + */ + private boolean shouldAdjustKeyWidths() { + Assert.checkState(isLandscapeMode()); + + DialpadKeyButton dialpadKeyButton = (DialpadKeyButton) findViewById(BUTTON_IDS[0]); + LinearLayout keyLayout = + (LinearLayout) dialpadKeyButton.findViewById(R.id.dialpad_key_layout); + final int width = keyLayout.getWidth(); + + for (int i = 1; i < BUTTON_IDS.length; i++) { + dialpadKeyButton = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); + keyLayout = (LinearLayout) dialpadKeyButton.findViewById(R.id.dialpad_key_layout); + if (width != keyLayout.getWidth()) { + return true; + } + } + + return false; + } + + /** + * Return true if not all digit key layouts have the same height. This method must be + * called when the device is in portrait mode. + */ + private boolean shouldAdjustDigitKeyHeights() { + Assert.checkState(!isLandscapeMode()); + + DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[0]); + LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + final int height = keyLayout.getHeight(); + + // BUTTON_IDS[i] is the resource ID for button i when 0 <= i && i <= 9. + // For example, BUTTON_IDS[3] is the resource ID for button "3" on the dialpad. + for (int i = 1; i <= 9; i++) { + dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); + keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + if (height != keyLayout.getHeight()) { + return true; + } + } + + return false; + } + + private void adjustKeySizes() { + if (isLandscapeMode()) { + adjustKeyWidths(); + } else { + adjustDigitKeyHeights(); + } + } + + /** + * Make the heights of all digit keys the same. + * + *

When the device is in portrait mode, we first find the maximum height among digit key + * layouts. Then for each key, we adjust the height of the layout containing letters/the + * voicemail icon to ensure the height of each digit key is the same. + * + *

A layout pass will be scheduled in this method by {@link + * LinearLayout#setLayoutParams(ViewGroup.LayoutParams)}. + */ + private void adjustDigitKeyHeights() { + Assert.checkState(!isLandscapeMode()); + + int maxHeight = 0; + + // BUTTON_IDS[i] is the resource ID for button i when 0 <= i && i <= 9. + // For example, BUTTON_IDS[3] is the resource ID for button "3" on the dialpad. + for (int i = 0; i <= 9; i++) { + DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); + LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + maxHeight = Math.max(maxHeight, keyLayout.getHeight()); + } + + for (int i = 0; i <= 9; i++) { + DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]); + LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + + DialpadTextView numberView = + (DialpadTextView) keyLayout.findViewById(R.id.dialpad_key_number); + MarginLayoutParams numberViewLayoutParams = + (MarginLayoutParams) numberView.getLayoutParams(); + + LinearLayout iconOrLettersLayout = + (LinearLayout) keyLayout.findViewById(R.id.dialpad_key_icon_or_letters_layout); + iconOrLettersLayout.setLayoutParams( + new LayoutParams( + LayoutParams.WRAP_CONTENT /* width */, + maxHeight + - numberView.getHeight() + - numberViewLayoutParams.topMargin + - numberViewLayoutParams.bottomMargin /* height */)); + } + } + + /** + * Make the widths of all keys the same. + * + *

When the device is in landscape mode, we first find the maximum width among key layouts. + * Then we adjust the width of each layout's horizontal placeholder so that each key has the + * same width. + * + *

A layout pass will be scheduled in this method by {@link + * View#setLayoutParams(ViewGroup.LayoutParams)}. + */ + private void adjustKeyWidths() { + Assert.checkState(isLandscapeMode()); + + int maxWidth = 0; + for (int buttonId : BUTTON_IDS) { + DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId); + LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + maxWidth = Math.max(maxWidth, keyLayout.getWidth()); + } + + for (int buttonId : BUTTON_IDS) { + DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(buttonId); + LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout); + View horizontalPlaceholder = + keyLayout.findViewById(R.id.dialpad_key_horizontal_placeholder); + horizontalPlaceholder.setLayoutParams( + new LayoutParams( + maxWidth - keyLayout.getWidth() /* width */, + LayoutParams.MATCH_PARENT /* height */)); + } + } + } } -- cgit v1.2.3