Skip to content

Commit

Permalink
[android] stop using Build.VERSION.SdkInt (#3783)
Browse files Browse the repository at this point in the history
We have a beautiful .NET 6 API we can use instead, that doesn't call
into Java (no JNI!):

https://docs.microsoft.com/dotnet/api/system.operatingsystem.isandroidversionatleast

Usage of `Build.VERSION.SdkInt` came from both Xamarin.Forms and
Xamarin.Essentials. We were caching the result of the value, but still
doing that work twice.

We can also use the pattern:

    OperatingSystem.IsAndroidVersionAtLeast((int)BuildVersionCodes.JellyBean)

`BuildVersionCodes` is a regular C# enum, and so the C# compiler will
strip this information away leaving just an integer in the final IL.

I used either an integer or the enum, depending on what the existing
code did.

Additionally, I went through any existing code checking old API levels and removed it.
The minimum API level for .NET 6 (dotnet/runtime & xamarin-android) is 21. So any
code looking for API levels 21 or lower, could just be removed.

I also removed code I found such as:

    public static int? TargetSdkVersion(this Context self)
    {
        return (int?)self?.ApplicationInfo?.TargetSdkVersion;
    }

This was only used in one place, and was checking API 17, so I just
removed it.

~~ Results ~~

Testing a `Release` build of `Maui.Controls.Sample.SingleProject.csproj`
on a Pixel 5 device:

    Before:
    12-16 14:41:19.289  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s739ms
    12-16 14:41:24.468  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s713ms
    12-16 14:41:29.867  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s917ms
    12-16 14:41:34.905  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s765ms
    12-16 14:41:40.132  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s719ms
    12-16 14:41:45.431  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s768ms
    12-16 14:41:50.608  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s716ms
    12-16 14:41:55.878  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s754ms
    12-16 14:42:01.157  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s754ms
    12-16 14:42:06.315  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s713ms
    Average(ms): 1755.8
    Std Err(ms): 19.1803139819046
    Std Dev(ms): 60.6534784199921

    After:
    12-16 14:45:35.208  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s737ms
    12-16 14:45:40.448  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s743ms
    12-16 14:45:45.663  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s715ms
    12-16 14:45:50.931  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s741ms
    12-16 14:45:56.161  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s712ms
    12-16 14:46:01.426  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s768ms
    12-16 14:46:06.574  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s699ms
    12-16 14:46:11.867  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s779ms
    12-16 14:46:16.979  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s694ms
    12-16 14:46:22.229  1741  1935 I ActivityTaskManager: Displayed com.microsoft.maui.sample/crc64dac46b470c4e9200.MainActivity: +1s728ms
    Average(ms): 1731.6
    Std Err(ms): 8.79924239163047
    Std Dev(ms): 27.8256476414596

This appears to maybe save ~24ms on startup for this app?
  • Loading branch information
jonathanpeppers authored Dec 17, 2021
1 parent 5f9edd1 commit 34e83cf
Show file tree
Hide file tree
Showing 56 changed files with 192 additions and 610 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,7 @@ void UpdateTextColor()
[PortHandler]
void UpdateCharacterSpacing()
{
if (Forms.IsLollipopOrNewer)
{
NativeButton.LetterSpacing = Element.CharacterSpacing.ToEm();
}

NativeButton.LetterSpacing = Element.CharacterSpacing.ToEm();
}

void IOnClickListener.OnClick(AView v) => ButtonElementManager.OnClick(Element, Element, v);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,7 @@ public override bool OnOptionsItemSelected(IMenuItem item)

public void SetStatusBarColor(AColor color)
{
if (Forms.IsLollipopOrNewer)
{
Window.SetStatusBarColor(color);
}
Window.SetStatusBarColor(color);
}

static void RegisterHandler(Type target, Type handler, Type filter)
Expand Down Expand Up @@ -247,15 +244,11 @@ void OnCreate(

OnStateChanged();

Profile.FramePartition("Forms.IsLollipopOrNewer");
if (Forms.IsLollipopOrNewer)
// Allow for the status bar color to be changed
if ((flags & ActivationFlags.DisableSetStatusBarColor) == 0)
{
// Allow for the status bar color to be changed
if ((flags & ActivationFlags.DisableSetStatusBarColor) == 0)
{
Profile.FramePartition("Set DrawsSysBarBkgrnds");
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
}
Profile.FramePartition("Set DrawsSysBarBkgrnds");
Window.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
}

Profile.FrameEnd();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public override void Draw(Canvas canvas)

if (Drawable != null)
{
if ((int)Forms.SdkInt >= 18 && backgroundDrawable != null)
if (backgroundDrawable != null)
{
var outlineBounds = backgroundDrawable.GetPaddingBounds(canvas.Width, canvas.Height);
var width = (float)canvas.Width;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,7 @@ void UpdateFont()
[PortHandler]
protected void UpdateCharacterSpacing()
{
if (Forms.IsLollipopOrNewer)
{
EditText.LetterSpacing = Element.CharacterSpacing.ToEm();
}
EditText.LetterSpacing = Element.CharacterSpacing.ToEm();
}

[PortHandler("Partially ported, still missing code related to TitleColor, etc.")]
Expand Down
18 changes: 1 addition & 17 deletions src/Compatibility/Core/src/Android/AppCompat/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -695,23 +695,7 @@ void UpdateBackgroundColor()
}
}

internal static int GenerateViewId()
{
// getting unique Id's is an art, and I consider myself the Jackson Pollock of the field
if ((int)Forms.SdkInt >= 17)
return global::Android.Views.View.GenerateViewId();

// Numbers higher than this range reserved for xml
// If we roll over, it can be exceptionally problematic for the user if they are still retaining things, android's internal implementation is
// basically identical to this except they do a lot of locking we don't have to because we know we only do this
// from the UI thread
if (s_id >= 0x00ffffff)
s_id = 0x00000400;

return s_id++;
}

static int s_id = 0x00000400;
internal static int GenerateViewId() => global::Android.Views.View.GenerateViewId();

#region Statics

Expand Down
38 changes: 5 additions & 33 deletions src/Compatibility/Core/src/Android/AppCompat/TabbedPageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ public class TabbedPageRenderer : VisualElementRenderer<TabbedPage>,
#pragma warning restore CS0618 // Type or member is obsolete
ViewPager.IOnPageChangeListener, IManageFragments, NavigationBarView.IOnItemSelectedListener
{
Drawable _backgroundDrawable;
Drawable _wrappedBackgroundDrawable;
ColorStateList _originalTabTextColors;
ColorStateList _orignalTabIconColors;

Expand Down Expand Up @@ -416,11 +414,7 @@ protected override void OnLayout(bool changed, int l, int t, int r, int b)

if (tabs.Visibility != ViewStates.Gone)
{
//MinimumHeight is only available on API 16+
if ((int)Forms.SdkInt >= 16)
tabsHeight = Math.Min(height, Math.Max(tabs.MeasuredHeight, tabs.MinimumHeight));
else
tabsHeight = Math.Min(height, tabs.MeasuredHeight);
tabsHeight = Math.Min(height, Math.Max(tabs.MeasuredHeight, tabs.MinimumHeight));
}

pager.Measure(MeasureSpecFactory.MakeMeasureSpec(width, MeasureSpecMode.AtMost), MeasureSpecFactory.MakeMeasureSpec(height, MeasureSpecMode.AtMost));
Expand Down Expand Up @@ -728,36 +722,14 @@ void UpdateBarBackgroundColor()
{
Color tintColor = Element.BarBackgroundColor;

if (Forms.IsLollipopOrNewer)
if (tintColor == null)
{
if (tintColor == null)
_tabLayout.BackgroundTintMode = null;
else
{
_tabLayout.BackgroundTintMode = PorterDuff.Mode.Src;
_tabLayout.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToAndroid());
}
_tabLayout.BackgroundTintMode = null;
}
else
{
if (tintColor == null && _backgroundDrawable != null)
_tabLayout.SetBackground(_backgroundDrawable);
else if (tintColor != null)
{
// if you don't create a new drawable then SetBackgroundColor
// just sets the color on the background drawable that's saved
// it doesn't create a new one
if (_backgroundDrawable == null && _tabLayout.Background != null)
{
_backgroundDrawable = _tabLayout.Background;
_wrappedBackgroundDrawable = ADrawableCompat.Wrap(_tabLayout.Background).Mutate();
}

if (_wrappedBackgroundDrawable != null)
_tabLayout.Background = _wrappedBackgroundDrawable;

_tabLayout.SetBackgroundColor(tintColor.ToAndroid());
}
_tabLayout.BackgroundTintMode = PorterDuff.Mode.Src;
_tabLayout.BackgroundTintList = ColorStateList.ValueOf(tintColor.ToAndroid());
}
}
}
Expand Down
17 changes: 5 additions & 12 deletions src/Compatibility/Core/src/Android/BorderBackgroundManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ public void UpdateDrawable()
shadowDx = 0;
shadowColor = _backgroundDrawable.PressedBackgroundColor.ToAndroid();
}
// Otherwise get values from the control (but only for supported APIs)
else if ((int)Forms.SdkInt >= 16)
// Otherwise get values from the control
else
{
shadowRadius = _renderer.ShadowRadius;
shadowDy = _renderer.ShadowDy;
Expand All @@ -151,16 +151,9 @@ public void UpdateDrawable()

if (!backgroundColorIsDefault || _drawOutlineWithBackground)
{
if (Forms.IsLollipopOrNewer)
{
var rippleColor = _backgroundDrawable.PressedBackgroundColor.ToAndroid();
_rippleDrawable = new RippleDrawable(ColorStateList.ValueOf(rippleColor), _backgroundDrawable, null);
Control.SetBackground(_rippleDrawable);
}
else
{
Control.SetBackground(_backgroundDrawable);
}
var rippleColor = _backgroundDrawable.PressedBackgroundColor.ToAndroid();
_rippleDrawable = new RippleDrawable(ColorStateList.ValueOf(rippleColor), _backgroundDrawable, null);
Control.SetBackground(_rippleDrawable);
}

_drawableEnabled = true;
Expand Down
8 changes: 2 additions & 6 deletions src/Compatibility/Core/src/Android/Cells/BaseCellView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ public BaseCellView(Context context, Cell cell) : base(context)

SetMinimumHeight((int)context.ToPixels(DefaultMinHeight));
_androidDefaultTextColor = Color.FromUint((uint)_mainText.CurrentTextColor);

if ((int)Forms.SdkInt > 16)
{
_mainText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
_detailText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
}
_mainText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
_detailText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
}

public AView AccessoryView { get; private set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,7 @@ void UpdateOnColor(SwitchCellView cell, SwitchCell switchCell)
}
else
{
if (Forms.SdkInt >= BuildVersionCodes.JellyBean)
{
aSwitch.TrackDrawable.SetColorFilter(switchCell.OnColor, FilterMode.Multiply);
}
aSwitch.TrackDrawable.SetColorFilter(switchCell.OnColor, FilterMode.Multiply);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal static class FlowDirectionExtensions
{
internal static void UpdateFlowDirection(this AView view, IVisualElementController controller)
{
if (view == null || controller == null || (int)Forms.SdkInt < 17)
if (view == null || controller == null)
return;

if (controller is IView v)
Expand All @@ -18,7 +18,6 @@ internal static void UpdateFlowDirection(this AView view, IVisualElementControll
return;
}

// if android:targetSdkVersion < 17 setting these has no effect
if (controller.EffectiveFlowDirection.IsRightToLeft())
{
view.LayoutDirection = ALayoutDirection.Rtl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ internal static class ScrollViewExtensions
{
internal static void HandleScrollBarVisibilityChange(this IScrollView scrollView)
{
if (Forms.SdkInt <= BuildVersionCodes.Kitkat)
return;

// According to the Android Documentation
// * <p>AwakenScrollBars method should be invoked every time a subclass directly updates
// *the scroll parameters.</ p >
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal static class TextAlignmentExtensions
{
internal static void UpdateHorizontalAlignment(this EditText view, TextAlignment alignment, bool hasRtlSupport, AGravityFlags orMask = AGravityFlags.NoGravity)
{
if ((int)Build.VERSION.SdkInt < 17 || !hasRtlSupport)
if (!hasRtlSupport)
view.Gravity = alignment.ToHorizontalGravityFlags() | orMask;
else
view.TextAlignment = alignment.ToTextAlignment();
Expand All @@ -22,7 +22,7 @@ internal static void UpdateVerticalAlignment(this EditText view, TextAlignment a

internal static void UpdateTextAlignment(this EditText view, TextAlignment horizontal, TextAlignment vertical)
{
if ((int)Build.VERSION.SdkInt < 17 || !view.Context.HasRtlSupport())
if (!view.Context.HasRtlSupport())
{
view.Gravity = vertical.ToVerticalGravityFlags() | horizontal.ToHorizontalGravityFlags();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,7 @@ void UpdateTextColor()
[PortHandler]
void UpdateCharacterSpacing()
{
if (Forms.IsLollipopOrNewer)
{
LetterSpacing = Button.CharacterSpacing.ToEm();
}
LetterSpacing = Button.CharacterSpacing.ToEm();
}

float IBorderVisualElementRenderer.ShadowRadius => ShadowRadius;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,7 @@ void UpdateGravity()
[PortHandler]
void UpdateCharacterSpacing()
{
if (Forms.IsLollipopOrNewer)
{
LetterSpacing = Element.CharacterSpacing.ToEm();
}
LetterSpacing = Element.CharacterSpacing.ToEm();
}

[PortHandler]
Expand Down
Loading

0 comments on commit 34e83cf

Please sign in to comment.