commit 817d33a8d69f67a2ba7baf321508f3613daa2a84 parent d794b4c0915eef7b155575a74416a5c0bff6fb6f Author: Ryan VanderMeulen <rvandermeulen@mozilla.com> Date: Thu, 30 Oct 2025 11:50:56 +0000 Bug 1991789 - Remove unnecessary Android version checks and workarounds. r=geckoview-reviewers,media-playback-reviewers,android-reviewers,geckoview-api-reviewers,gfx-reviewers,gsvelto,jnicol,mcarare,ohall,jonalmeida,karlt,m_kato Differential Revision: https://phabricator.services.mozilla.com/D270354 Diffstat:
46 files changed, 227 insertions(+), 666 deletions(-)
diff --git a/dom/media/moz.build b/dom/media/moz.build @@ -274,6 +274,8 @@ UNIFIED_SOURCES += [ "CloneableWithRangeMediaResource.cpp", "CrossGraphPort.cpp", "CubebInputStream.cpp", + "CubebUtils.cpp", + "DecoderTraits.cpp", "DeviceInputTrack.cpp", "DOMMediaStream.cpp", "ExternalEngineStateMachine.cpp", @@ -332,20 +334,11 @@ else: if CONFIG["ENABLE_TESTS"] or CONFIG["FUZZING"]: UNIFIED_SOURCES += ["MockCubeb.cpp"] -# CubebUtils.cpp needs to be built separately due to what appears to be some kind -# of compiler bug on Android 4.2 x86 opt. See bug 1408459. -# DecoderTraits.cpp needs to be built separately because of Mac OS X headers. # MediaData.cpp : ambiguous compilation error caused by Mac OS X headers. SOURCES += [ - "CubebUtils.cpp", - "DecoderTraits.cpp", "MediaData.cpp", ] -# Some codec-related code uses multi-character constants, which GCC and clang -# warn about. Suppress turning this warning into an error. -SOURCES["DecoderTraits.cpp"].flags += ["-Wno-error=multichar"] - if CONFIG["MOZ_WEBRTC"]: XPCOM_MANIFESTS += [ "components.conf", diff --git a/dom/media/platforms/android/RemoteDataDecoder.cpp b/dom/media/platforms/android/RemoteDataDecoder.cpp @@ -996,13 +996,6 @@ static CryptoInfoResult GetCryptoInfoFromSample(const MediaRawData* aSample) { return CryptoInfoResult(cryptoInfo); } - static bool supportsCBCS = java::CodecProxy::SupportsCBCS(); - if ((cryptoObj.mCryptoScheme == CryptoScheme::Cbcs || - cryptoObj.mCryptoScheme == CryptoScheme::Cbcs_1_9) && - !supportsCBCS) { - return CryptoInfoResult(NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR); - } - nsresult rv = java::sdk::MediaCodec::CryptoInfo::New(&cryptoInfo); NS_ENSURE_SUCCESS(rv, CryptoInfoResult(rv)); diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp @@ -1847,23 +1847,19 @@ void GLContext::AttachBuffersToFB(GLuint colorTex, GLuint colorRB, fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, target, colorTex, 0); } else if (colorRB) { - // On the Android 4.3 emulator, IsRenderbuffer may return false incorrectly. - MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB) || - Renderer() == GLRenderer::AndroidEmulator); + MOZ_GL_ASSERT(this, fIsRenderbuffer(colorRB)); fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, colorRB); } if (depthRB) { - MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB) || - Renderer() == GLRenderer::AndroidEmulator); + MOZ_GL_ASSERT(this, fIsRenderbuffer(depthRB)); fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, depthRB); } if (stencilRB) { - MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB) || - Renderer() == GLRenderer::AndroidEmulator); + MOZ_GL_ASSERT(this, fIsRenderbuffer(stencilRB)); fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, stencilRB); } diff --git a/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt b/mobile/android/fenix/app/src/androidTest/java/org/mozilla/fenix/helpers/AppAndSystemHelper.kt @@ -488,16 +488,14 @@ object AppAndSystemHelper { .className("android.widget.Button"), ) - if (Build.VERSION.SDK_INT >= 23) { - if (whileUsingTheAppPermissionButton.waitForExists(waitingTimeShort)) { - Log.i(TAG, "grantSystemPermission: Trying to click the \"While using the app\" button.") - whileUsingTheAppPermissionButton.click() - Log.i(TAG, "grantSystemPermission: Clicked the \"While using the app\" button.") - } else if (allowPermissionButton.waitForExists(waitingTimeShort)) { - Log.i(TAG, "grantSystemPermission: Trying to click the \"Allow\" button.") - allowPermissionButton.click() - Log.i(TAG, "grantSystemPermission: Clicked the \"Allow\" button.") - } + if (whileUsingTheAppPermissionButton.waitForExists(waitingTimeShort)) { + Log.i(TAG, "grantSystemPermission: Trying to click the \"While using the app\" button.") + whileUsingTheAppPermissionButton.click() + Log.i(TAG, "grantSystemPermission: Clicked the \"While using the app\" button.") + } else if (allowPermissionButton.waitForExists(waitingTimeShort)) { + Log.i(TAG, "grantSystemPermission: Trying to click the \"Allow\" button.") + allowPermissionButton.click() + Log.i(TAG, "grantSystemPermission: Clicked the \"Allow\" button.") } } diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/BaselineProfilesSwitchTabsBenchmark.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/BaselineProfilesSwitchTabsBenchmark.kt @@ -8,7 +8,6 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.os.SystemClock -import androidx.annotation.RequiresApi import androidx.benchmark.macro.BaselineProfileMode import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.StartupMode @@ -61,7 +60,6 @@ import org.mozilla.fenix.benchmark.utils.url * and the [instrumentation arguments documentation](https://d.android.com/topic/performance/benchmarking/macrobenchmark-instrumentation-args). **/ @RunWith(Parameterized::class) -@RequiresApi(Build.VERSION_CODES.N) @BaselineProfileMacrobenchmark class BaselineProfilesSwitchTabsBenchmark( private val useComposableToolbar: Boolean, diff --git a/mobile/android/focus-android/app/src/androidTest/java/org/mozilla/focus/helpers/TestHelper.kt b/mobile/android/focus-android/app/src/androidTest/java/org/mozilla/focus/helpers/TestHelper.kt @@ -14,7 +14,6 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.Color import android.os.Build -import android.os.Build.VERSION.SDK_INT import android.os.storage.StorageManager import android.os.storage.StorageVolume import android.util.Log @@ -186,19 +185,17 @@ object TestHelper { // Method for granting app permission to access location/camera/mic fun grantAppPermission() { - if (SDK_INT >= 23) { - val permissionOption = - mDevice.findObject( - UiSelector().textContains( - when { - SDK_INT >= 30 -> "While using the app" - else -> "Allow" - }, - ), - ) - permissionOption.waitForExists(waitingTime) - permissionOption.click() - } + val permissionOption = + mDevice.findObject( + UiSelector().textContains( + when { + Build.VERSION.SDK_INT >= 30 -> "While using the app" + else -> "Allow" + }, + ), + ) + permissionOption.waitForExists(waitingTime) + permissionOption.click() } fun UiAutomation.executeShellCommandBlocking(command: String) { diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt @@ -44,7 +44,6 @@ import android.widget.FrameLayout; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.UiThread; import androidx.core.view.OnApplyWindowInsetsListener; import androidx.core.view.WindowInsetsCompat; @@ -402,8 +401,8 @@ package org.mozilla.geckoview { public static final class Autofill.Session { method @UiThread public void autofill(@NonNull SparseArray<CharSequence>); method @NonNull @UiThread public Autofill.NodeData dataFor(@NonNull Autofill.Node); - method @RequiresApi(value=23) @UiThread public void fillViewStructure(@NonNull View, @NonNull ViewStructure, int); - method @RequiresApi(value=23) @UiThread public void fillViewStructure(@NonNull Autofill.Node, @NonNull View, @NonNull ViewStructure, int); + method @UiThread public void fillViewStructure(@NonNull View, @NonNull ViewStructure, int); + method @UiThread public void fillViewStructure(@NonNull Autofill.Node, @NonNull View, @NonNull ViewStructure, int); method @NonNull @UiThread public Rect getDefaultDimensions(); method @Nullable @UiThread public Autofill.Node getFocused(); method @Nullable @UiThread public Autofill.NodeData getFocusedData(); @@ -1332,7 +1331,7 @@ package org.mozilla.geckoview { method @UiThread default public void onKill(@NonNull GeckoSession); method @UiThread default public void onMetaViewportFitChange(@NonNull GeckoSession, @NonNull String); method @UiThread default public void onPaintStatusReset(@NonNull GeckoSession); - method @RequiresApi(value=24) @UiThread default public void onPointerIconChange(@NonNull GeckoSession, @NonNull PointerIcon); + method @UiThread default public void onPointerIconChange(@NonNull GeckoSession, @NonNull PointerIcon); method @UiThread default public void onPreviewImage(@NonNull GeckoSession, @NonNull String); method @UiThread default public void onShowDynamicToolbar(@NonNull GeckoSession); method @Nullable @UiThread default public GeckoResult<SlowScriptResponse> onSlowScript(@NonNull GeckoSession, @NonNull String); @@ -2113,7 +2112,7 @@ package org.mozilla.geckoview { method public void coverUntilFirstPaint(int); method public void dispatchDraw(@Nullable Canvas); method @Nullable public GeckoView.ActivityContextDelegate getActivityContextDelegate(); - method @RequiresApi(value=26) public boolean getAutofillEnabled(); + method public boolean getAutofillEnabled(); method @NonNull public PanZoomController getPanZoomController(); method @Nullable public GeckoSession.PrintDelegate getPrintDelegate(); method public void getPrintDelegate(@Nullable GeckoSession.PrintDelegate); @@ -2124,7 +2123,7 @@ package org.mozilla.geckoview { method @Nullable @UiThread public GeckoSession releaseSession(); method @UiThread public void removeWindowInsetsListener(@NonNull String); method public void setActivityContextDelegate(@Nullable GeckoView.ActivityContextDelegate); - method @RequiresApi(value=26) public void setAutofillEnabled(boolean); + method public void setAutofillEnabled(boolean); method public void setDynamicToolbarMaxHeight(int); method @UiThread public void setSession(@NonNull GeckoSession); method public void setVerticalClipping(int); diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/DragAndDropTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/DragAndDropTest.kt @@ -12,7 +12,6 @@ import android.view.DragEvent import android.view.MotionEvent import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest -import androidx.test.filters.SdkSuppress import org.hamcrest.Matchers.equalTo import org.json.JSONObject import org.junit.Ignore @@ -21,7 +20,6 @@ import org.junit.runner.RunWith import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay @RunWith(AndroidJUnit4::class) -@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) @MediumTest class DragAndDropTest : BaseSessionTest() { // DragEvent has no constructor, so we create it via Java reflection. diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoViewTest.kt @@ -17,7 +17,6 @@ import android.view.autofill.AutofillValue import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest -import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import org.hamcrest.Matchers.equalTo import org.junit.* @@ -330,7 +329,6 @@ class GeckoViewTest : BaseSessionTest() { @Test @NullDelegate(Autofill.Delegate::class) - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) fun autofillWithNoSession() { mainSession.loadTestPath(FORMS_XORIGIN_HTML_PATH) mainSession.waitForPageStop() diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt @@ -48,9 +48,6 @@ class PermissionDelegateTest : BaseSessionTest() { get() = InstrumentationRegistry.getInstrumentation().targetContext private fun hasPermission(permission: String): Boolean { - if (Build.VERSION.SDK_INT < 23) { - return true - } return PackageManager.PERMISSION_GRANTED == InstrumentationRegistry.getInstrumentation().targetContext.checkSelfPermission( permission, diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt @@ -14,7 +14,6 @@ import android.util.Base64 import androidx.core.net.toUri import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.filters.MediumTest -import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import org.hamcrest.Matcher import org.hamcrest.Matchers.arrayContainingInAnyOrder @@ -169,7 +168,6 @@ class SelectionActionDelegateTest : BaseSessionTest() { } } - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) @Test fun request_html() { if (editable) { @@ -272,7 +270,6 @@ class SelectionActionDelegateTest : BaseSessionTest() { } } - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O) @Test fun pasteAsPlainText() = assumingEditable(true) { assumeThat("Paste as plain text works on content editable", type, not(equalTo(ContentType.EDITABLE_ELEMENT))) diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt @@ -21,7 +21,6 @@ import android.view.inputmethod.InputConnection import android.view.inputmethod.InputContentInfo import androidx.core.net.toUri import androidx.test.filters.MediumTest -import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import org.hamcrest.Matchers.equalTo import org.hamcrest.Matchers.not @@ -929,7 +928,6 @@ class TextInputDelegateTest : BaseSessionTest() { ) } - @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N_MR1) @WithDisplay(width = 512, height = 512) // Child process updates require having a display. @Test diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/Clipboard.java @@ -170,17 +170,10 @@ public final class Clipboard { // which is a subclass of android.text.ClipboardManager. final ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (isPrivateData || Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - final PersistableBundle extras = new PersistableBundle(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - extras.putLong("org.mozilla.gecko.clipboard", System.currentTimeMillis()); - } - if (isPrivateData) { - extras.putBoolean("android.content.extra.IS_SENSITIVE", true); - } - clipData.getDescription().setExtras(extras); - } + if (isPrivateData) { + final PersistableBundle extras = new PersistableBundle(); + extras.putBoolean("android.content.extra.IS_SENSITIVE", true); + clipData.getDescription().setExtras(extras); } try { cm.setPrimaryClip(clipData); @@ -297,29 +290,13 @@ public final class Clipboard { } private static long getClipboardTimestamp(final Context context) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return 0; - } - final ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); final ClipDescription description = cm.getPrimaryClipDescription(); if (description == null) { return 0; } - - // getTimestamp is added in API Level 26, - // https://developer.android.com/reference/kotlin/android/content/ClipDescription?hl=en#gettimestamp - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - return description.getTimestamp(); - } - - final PersistableBundle extras = description.getExtras(); - if (extras == null) { - return 0; - } - - return extras.getLong("org.mozilla.gecko.clipboard", 0); + return description.getTimestamp(); } public static void updateSequenceNumber(final Context context) { @@ -334,17 +311,6 @@ public final class Clipboard { sClipboardSequenceNumber.incrementAndGet(); } - public static void onPause() { - // If ClipDescription#getTimestamp() is not supported, the clipboard - // timestamp will be retrieved from the extended data in the clip - // description. However, this becomes unreliable if the application is - // paused, as other applications can also set the same extended data in - // the clip description. Therefore, clear it. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - sClipboardTimestamp.set(0); - } - } - /** Get clipboard sequence number. */ @WrapForJNI(calledFrom = "gecko") private static long getSequenceNumber(final Context context) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java @@ -65,7 +65,6 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.nio.ByteBuffer; import java.util.List; -import java.util.Locale; import java.util.StringTokenizer; import org.jetbrains.annotations.NotNull; import org.mozilla.gecko.annotation.RobocopTarget; @@ -513,9 +512,7 @@ public class GeckoAppShell { final float accuracy = location.hasAccuracy() ? location.getAccuracy() : Float.NaN; final float altitudeAccuracy = - Build.VERSION.SDK_INT >= 26 && location.hasVerticalAccuracy() - ? location.getVerticalAccuracyMeters() - : Float.NaN; + location.hasVerticalAccuracy() ? location.getVerticalAccuracyMeters() : Float.NaN; final float speed = location.hasSpeed() ? location.getSpeed() : Float.NaN; @@ -934,29 +931,10 @@ public class GeckoAppShell { @WrapForJNI(calledFrom = "gecko") private static boolean hasHDRScreen() { - if (Build.VERSION.SDK_INT < 24) { - return false; - } - final WindowManager wm = - (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); - final Display display = wm.getDefaultDisplay(); - if (Build.VERSION.SDK_INT >= 26) { - return display.isHdr(); - } - final Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities(); - if (hdrCapabilities == null) { - return false; - } - final int[] supportedHdrTypes = hdrCapabilities.getSupportedHdrTypes(); - for (final int type : supportedHdrTypes) { - if (type == Display.HdrCapabilities.HDR_TYPE_HDR10 - || type == Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS - || type == Display.HdrCapabilities.HDR_TYPE_HLG - || type == Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION) { - return true; - } - } - return false; + final Display display = + ((DisplayManager) getApplicationContext().getSystemService(Context.DISPLAY_SERVICE)) + .getDisplay(Display.DEFAULT_DISPLAY); + return display != null && display.isHdr(); } @WrapForJNI(calledFrom = "gecko") @@ -1106,10 +1084,6 @@ public class GeckoAppShell { @WrapForJNI(calledFrom = "gecko", exceptionMode = "nsresult") private static String getDNSDomains() { - if (Build.VERSION.SDK_INT < 23) { - return ""; - } - ensureConnectivityManager(); final Network net = sConnectivityManager.getActiveNetwork(); if (net == null) { @@ -1174,11 +1148,7 @@ public class GeckoAppShell { // TODO(m_kato): // Android 16 will have `layout related APIs such as setLayoutLabelNonLocalized // to get keyboard layout label. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return ims.getLanguageTag(); - } else { - return ims.getLocale(); - } + return ims.getLanguageTag(); } @WrapForJNI(calledFrom = "gecko") @@ -1482,8 +1452,7 @@ public class GeckoAppShell { if (hasInputDeviceSource(sources, InputDevice.SOURCE_STYLUS)) { result |= POINTING_DEVICE_PEN; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && hasInputDeviceSource(sources, InputDevice.SOURCE_BLUETOOTH_STYLUS)) { + if (hasInputDeviceSource(sources, InputDevice.SOURCE_BLUETOOTH_STYLUS)) { result |= POINTING_DEVICE_PEN; } @@ -1716,18 +1685,12 @@ public class GeckoAppShell { @WrapForJNI public static String[] getDefaultLocales() { - // XXX We may have to convert some language codes such as "id" vs "in". - if (Build.VERSION.SDK_INT >= 24) { - final LocaleList localeList = LocaleList.getDefault(); - final String[] locales = new String[localeList.size()]; - for (int i = 0; i < localeList.size(); i++) { - locales[i] = localeList.get(i).toLanguageTag(); - } - return locales; + final LocaleList list = LocaleList.getDefault(); + final int n = list.size(); + final String[] locales = new String[n]; + for (int i = 0; i < n; i++) { + locales[i] = list.get(i).toLanguageTag(); } - final String[] locales = new String[1]; - final Locale locale = Locale.getDefault(); - locales[0] = locale.toLanguageTag(); return locales; } @@ -1750,11 +1713,6 @@ public class GeckoAppShell { @WrapForJNI(calledFrom = "gecko") private static int getMemoryUsage(final String stateName) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // No API to get Java heap usages. - return -1; - } - final Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memInfo); final String usage = memInfo.getMemoryStat(stateName); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java @@ -11,17 +11,14 @@ import android.content.ClipDescription; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Point; -import android.os.Build; import android.text.TextUtils; import android.util.Log; import android.view.DragEvent; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import org.mozilla.gecko.annotation.WrapForJNI; -@RequiresApi(Build.VERSION_CODES.N) public class GeckoDragAndDrop { private static final String LOGTAG = "GeckoDragAndDrop"; private static final boolean DEBUG = false; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoNetworkManager.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoNetworkManager.java @@ -15,7 +15,6 @@ import android.net.DhcpInfo; import android.net.Proxy; import android.net.ProxyInfo; import android.net.wifi.WifiManager; -import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -119,11 +118,6 @@ public class GeckoNetworkManager extends BroadcastReceiver { } private void getProxyInfoAndReport(final Context aContext) { - // getDefaultProxy() added in API 23. - if (Build.VERSION.SDK_INT < 23) { - return; - } - if (mCurrentState != ManagerState.OnNoListeners && mCurrentState != ManagerState.OnWithListeners) { return; @@ -451,9 +445,7 @@ public class GeckoNetworkManager extends BroadcastReceiver { private static void registerBroadcastReceiver( final Context context, final BroadcastReceiver receiver) { final IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); - if (Build.VERSION.SDK_INT >= 23) { - filter.addAction(Proxy.PROXY_CHANGE_ACTION); - } + filter.addAction(Proxy.PROXY_CHANGE_ACTION); context.registerReceiver(receiver, filter); } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java @@ -6,13 +6,11 @@ package org.mozilla.gecko; import android.content.Context; -import android.os.Build; import android.provider.Settings.Secure; import android.view.View; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import java.util.Collection; -import java.util.Locale; public final class InputMethods { public static final String METHOD_ANDROID_LATINIME = "com.android.inputmethod.latin/.LatinIME"; @@ -101,13 +99,6 @@ public final class InputMethods { return METHOD_SONY.equals(inputMethod); } - // Workaround for bug 1818268 - Unexpected crash on Galaxy J7 - public static boolean dontOverrideCommitText() { - return Build.VERSION.SDK_INT == 23 - && Build.MANUFACTURER.toLowerCase(Locale.ROOT).equals("samsung") - && Build.MODEL.startsWith("SM-J700F"); - } - // TODO: Replace usages by definition in EditorInfoCompat once available (bug 1385726). public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 0x1000000; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/SpeechSynthesisService.java @@ -7,7 +7,6 @@ package org.mozilla.gecko; import android.content.Context; -import android.os.Build; import android.speech.tts.TextToSpeech; import android.speech.tts.UtteranceProgressListener; import android.util.Log; @@ -89,14 +88,11 @@ public class SpeechSynthesisService { } private static Set<Locale> getAvailableLanguages() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - // While this method was introduced in 21, it seems that it - // has not been implemented in the speech service side until 23. - final Set<Locale> availableLanguages = getTTS().getAvailableLanguages(); - if (availableLanguages != null) { - return availableLanguages; - } + final Set<Locale> availableLanguages = getTTS().getAvailableLanguages(); + if (availableLanguages != null) { + return availableLanguages; } + final Set<Locale> locales = new HashSet<Locale>(); for (final Locale locale : Locale.getAvailableLocales()) { if (locale.getVariant().isEmpty() && getTTS().isLanguageAvailable(locale) > 0) { @@ -218,10 +214,5 @@ public class SpeechSynthesisService { } getTTS().stop(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - // Android M has onStop method. If Android L or above, dispatch - // event - dispatchEnd(null); - } } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurfaceTexture.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/GeckoSurfaceTexture.java @@ -6,12 +6,10 @@ package org.mozilla.gecko.gfx; import android.graphics.SurfaceTexture; -import android.os.Build; import android.util.Log; import android.util.LongSparseArray; import java.util.LinkedList; import java.util.concurrent.atomic.AtomicInteger; -import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.mozglue.JNIObject; @@ -226,12 +224,6 @@ import org.mozilla.gecko.mozglue.JNIObject; } public static GeckoSurfaceTexture acquire(final boolean singleBufferMode, final long handle) { - // Attempting to create a SurfaceTexture from an isolated process on Android versions prior to - // 8.0 results in an indefinite hang. See bug 1706656. - if (GeckoAppShell.isIsolatedProcess() && Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - return null; - } - synchronized (sSurfaceTextures) { // We want to limit the maximum number of SurfaceTextures at any one time. // This is because they use a large number of fds, and once the process' limit diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/CodecProxy.java @@ -8,13 +8,10 @@ import android.media.MediaCodec; import android.media.MediaCodec.BufferInfo; import android.media.MediaCodec.CryptoInfo; import android.media.MediaFormat; -import android.os.Build; import android.os.DeadObjectException; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; -import androidx.annotation.ChecksSdkIntAtLeast; -import androidx.annotation.RequiresApi; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Queue; @@ -484,19 +481,10 @@ public final class CodecProxy { return buffer; } - @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N_MR1) - @WrapForJNI - public static boolean supportsCBCS() { - // Android N/API-24 supports CBCS but there seems to be a bug. - // See https://github.com/google/ExoPlayer/issues/4022 - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1; - } - - @RequiresApi(api = Build.VERSION_CODES.N_MR1) @WrapForJNI public static boolean setCryptoPatternIfNeeded( final CryptoInfo info, final int blocksToEncrypt, final int blocksToSkip) { - if (supportsCBCS() && (blocksToEncrypt > 0 || blocksToSkip > 0)) { + if (blocksToEncrypt > 0 || blocksToSkip > 0) { info.setPattern(new CryptoInfo.Pattern(blocksToEncrypt, blocksToSkip)); return true; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/FormatParam.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/FormatParam.java @@ -5,7 +5,6 @@ package org.mozilla.gecko.media; import android.media.MediaFormat; -import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -121,14 +120,12 @@ public final class FormatParam implements Parcelable { if (bundle.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) { mFormat.setInteger(MediaFormat.KEY_SLICE_HEIGHT, bundle.getInt(MediaFormat.KEY_SLICE_HEIGHT)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (bundle.containsKey(MediaFormat.KEY_COLOR_RANGE)) { - mFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, bundle.getInt(MediaFormat.KEY_COLOR_RANGE)); - } - if (bundle.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { - mFormat.setInteger( - MediaFormat.KEY_COLOR_STANDARD, bundle.getInt(MediaFormat.KEY_COLOR_STANDARD)); - } + if (bundle.containsKey(MediaFormat.KEY_COLOR_RANGE)) { + mFormat.setInteger(MediaFormat.KEY_COLOR_RANGE, bundle.getInt(MediaFormat.KEY_COLOR_RANGE)); + } + if (bundle.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { + mFormat.setInteger( + MediaFormat.KEY_COLOR_STANDARD, bundle.getInt(MediaFormat.KEY_COLOR_STANDARD)); } } @@ -185,14 +182,12 @@ public final class FormatParam implements Parcelable { if (mFormat.containsKey(MediaFormat.KEY_SLICE_HEIGHT)) { bundle.putInt(MediaFormat.KEY_SLICE_HEIGHT, mFormat.getInteger(MediaFormat.KEY_SLICE_HEIGHT)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - if (mFormat.containsKey(MediaFormat.KEY_COLOR_RANGE)) { - bundle.putInt(MediaFormat.KEY_COLOR_RANGE, mFormat.getInteger(MediaFormat.KEY_COLOR_RANGE)); - } - if (mFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { - bundle.putInt( - MediaFormat.KEY_COLOR_STANDARD, mFormat.getInteger(MediaFormat.KEY_COLOR_STANDARD)); - } + if (mFormat.containsKey(MediaFormat.KEY_COLOR_RANGE)) { + bundle.putInt(MediaFormat.KEY_COLOR_RANGE, mFormat.getInteger(MediaFormat.KEY_COLOR_RANGE)); + } + if (mFormat.containsKey(MediaFormat.KEY_COLOR_STANDARD)) { + bundle.putInt( + MediaFormat.KEY_COLOR_STANDARD, mFormat.getInteger(MediaFormat.KEY_COLOR_STANDARD)); } return bundle; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV21.java @@ -9,7 +9,6 @@ import android.media.MediaCrypto; import android.media.MediaDrm; import android.media.NotProvisionedException; import android.os.AsyncTask; -import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; @@ -671,9 +670,7 @@ public class GeckoMediaDrmBridgeV21 implements GeckoMediaDrm { // The EME spec says the messageType is only for optimization and optional. // Send 'License_request' as default when it's not available. int requestType = LICENSE_REQUEST_INITIAL; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - requestType = request.getRequestType(); - } + requestType = request.getRequestType(); onSessionMessage(session, requestType, request.getData()); } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/GeckoMediaDrmBridgeV23.java @@ -4,14 +4,10 @@ package org.mozilla.gecko.media; -import static android.os.Build.VERSION_CODES.M; - import android.media.MediaDrm; import android.util.Log; -import androidx.annotation.RequiresApi; import java.util.List; -@RequiresApi(M) public class GeckoMediaDrmBridgeV23 extends GeckoMediaDrmBridgeV21 { private static final boolean DEBUG = false; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java @@ -6,9 +6,7 @@ package org.mozilla.gecko.media; import android.media.MediaCrypto; import android.media.MediaDrm; -import android.os.Build; import android.util.Log; -import androidx.annotation.ChecksSdkIntAtLeast; import java.util.ArrayList; import java.util.UUID; import org.mozilla.gecko.annotation.WrapForJNI; @@ -37,22 +35,8 @@ public final class MediaDrmProxy { private GeckoMediaDrm mImpl; private String mDrmStubId; - @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.M) - private static boolean isSystemSupported() { - // Support versions >= Marshmallow - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - if (DEBUG) - Log.d(LOGTAG, "System Not supported !!, current SDK version is " + Build.VERSION.SDK_INT); - return false; - } - return true; - } - @WrapForJNI public static boolean isSchemeSupported(final String keySystem) { - if (!isSystemSupported()) { - return false; - } if (keySystem.equals(WIDEVINE_KEY_SYSTEM)) { return MediaDrm.isCryptoSchemeSupported(WIDEVINE_SCHEME_UUID) && MediaCrypto.isCryptoSchemeSupported(WIDEVINE_SCHEME_UUID); @@ -63,9 +47,6 @@ public final class MediaDrmProxy { @WrapForJNI public static boolean IsCryptoSchemeSupported(final String keySystem, final String container) { - if (!isSystemSupported()) { - return false; - } if (keySystem.equals(WIDEVINE_KEY_SYSTEM)) { return MediaDrm.isCryptoSchemeSupported(WIDEVINE_SCHEME_UUID, container); } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/RemoteMediaDrmBridgeStub.java @@ -5,7 +5,6 @@ package org.mozilla.gecko.media; import android.media.MediaCrypto; -import android.os.Build; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; @@ -143,11 +142,7 @@ final class RemoteMediaDrmBridgeStub extends IMediaDrmBridge.Stub RemoteMediaDrmBridgeStub(final String keySystem, final String stubId) throws RemoteException { try { - if (Build.VERSION.SDK_INT < 23) { - mBridge = new GeckoMediaDrmBridgeV21(keySystem); - } else { - mBridge = new GeckoMediaDrmBridgeV23(keySystem); - } + mBridge = new GeckoMediaDrmBridgeV23(keySystem); mStubId = stubId; mBridgeStubs.add(this); } catch (final Exception e) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Sample.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/Sample.java @@ -11,7 +11,6 @@ import android.media.MediaCodec.CryptoInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import androidx.annotation.ChecksSdkIntAtLeast; import java.lang.reflect.Field; import java.nio.ByteBuffer; import org.mozilla.gecko.annotation.WrapForJNI; @@ -69,11 +68,10 @@ public final class Sample implements Parcelable { cryptoInfo = new CryptoInfo(); } cryptoInfo.set(numSubSamples, numBytesOfClearData, numBytesOfEncryptedData, key, iv, mode); - if (supportsCryptoPattern()) { - final int numEncryptBlocks = in.readInt(); - final int numSkipBlocks = in.readInt(); - cryptoInfo.setPattern(new CryptoInfo.Pattern(numEncryptBlocks, numSkipBlocks)); - } + + final int numEncryptBlocks = in.readInt(); + final int numSkipBlocks = in.readInt(); + cryptoInfo.setPattern(new CryptoInfo.Pattern(numEncryptBlocks, numSkipBlocks)); } public Sample set(final BufferInfo info, final CryptoInfo cryptoInfo) { @@ -110,13 +108,11 @@ public final class Sample implements Parcelable { // synthesize it by creating a subsample as big as the sample itself. cryptoInfo.set(1, new int[] {0}, new int[] {info.size}, crypto.key, crypto.iv, crypto.mode); } - if (supportsCryptoPattern()) { - final CryptoInfo.Pattern pattern = getCryptoPatternCompat(crypto); - if (pattern == null) { - return; - } - cryptoInfo.setPattern(pattern); + final CryptoInfo.Pattern pattern = getCryptoPatternCompat(crypto); + if (pattern == null) { + return; } + cryptoInfo.setPattern(pattern); } @WrapForJNI @@ -209,16 +205,14 @@ public final class Sample implements Parcelable { dest.writeIntArray(cryptoInfo.numBytesOfClearData); dest.writeIntArray(cryptoInfo.numBytesOfEncryptedData); dest.writeInt(cryptoInfo.numSubSamples); - if (supportsCryptoPattern()) { - final CryptoInfo.Pattern pattern = getCryptoPatternCompat(cryptoInfo); - if (pattern != null) { - dest.writeInt(pattern.getEncryptBlocks()); - dest.writeInt(pattern.getSkipBlocks()); - } else { - // Couldn't get pattern - write default values - dest.writeInt(0); - dest.writeInt(0); - } + final CryptoInfo.Pattern pattern = getCryptoPatternCompat(cryptoInfo); + if (pattern != null) { + dest.writeInt(pattern.getEncryptBlocks()); + dest.writeInt(pattern.getSkipBlocks()); + } else { + // Couldn't get pattern - write default values + dest.writeInt(0); + dest.writeInt(0); } } else { dest.writeInt(0); @@ -265,35 +259,22 @@ public final class Sample implements Parcelable { return str.toString(); } - @ChecksSdkIntAtLeast(api = android.os.Build.VERSION_CODES.N) - public static boolean supportsCryptoPattern() { - return Build.VERSION.SDK_INT >= 24; - } - @SuppressLint("DiscouragedPrivateApi") public static CryptoInfo.Pattern getCryptoPatternCompat(final CryptoInfo cryptoInfo) { - if (!supportsCryptoPattern()) { - return null; - } // getPattern() added in API 31: // https://developer.android.com/reference/android/media/MediaCodec.CryptoInfo#getPattern() if (Build.VERSION.SDK_INT >= 31) { return cryptoInfo.getPattern(); } - // CryptoInfo.Pattern added in API 24: - // https://developer.android.com/reference/android/media/MediaCodec.CryptoInfo.Pattern - if (Build.VERSION.SDK_INT >= 24) { - try { - // Without getPattern(), no way to access the pattern without reflection. - // https://cs.android.com/android/platform/superproject/+/android-11.0.0_r1:frameworks/base/media/java/android/media/MediaCodec.java;l=2718;drc=3c715d5778e15dc84082e63dc65b382d31fe8e45 - final Field patternField = CryptoInfo.class.getDeclaredField("pattern"); - patternField.setAccessible(true); - return (CryptoInfo.Pattern) patternField.get(cryptoInfo); - } catch (final NoSuchFieldException | IllegalAccessException e) { - return null; - } + try { + // Without getPattern(), no way to access the pattern without reflection. + // https://cs.android.com/android/platform/superproject/+/android-11.0.0_r1:frameworks/base/media/java/android/media/MediaCodec.java;l=2718;drc=3c715d5778e15dc84082e63dc65b382d31fe8e45 + final Field patternField = CryptoInfo.class.getDeclaredField("pattern"); + patternField.setAccessible(true); + return (CryptoInfo.Pattern) patternField.get(cryptoInfo); + } catch (final NoSuchFieldException | IllegalAccessException e) { + return null; } - return null; } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/GeckoLoader.java @@ -172,7 +172,6 @@ public final class GeckoLoader { "MOZ_ANDROID_CRASH_HANDLER=" + context.getPackageName() + "/" + crashHandler.getName()); } - putenv("MOZ_ANDROID_DEVICE_SDK_VERSION=" + Build.VERSION.SDK_INT); putenv("MOZ_ANDROID_CPU_ABI=" + Build.CPU_ABI); // env from extras could have reset out linker flags; set them again. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/GeckoBundle.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/GeckoBundle.java @@ -8,7 +8,6 @@ package org.mozilla.gecko.util; import android.graphics.Point; import android.graphics.PointF; import android.graphics.RectF; -import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -960,25 +959,11 @@ public final class GeckoBundle implements Parcelable { jsonArray.put(element == null ? JSONObject.NULL : element.toJSONObject()); } jsonValue = jsonArray; - } else if (Build.VERSION.SDK_INT >= 19) { - // gradle task (testWithGeckoBinariesDebugUnitTest) won't use this since that unit test - // runs on build task. - final Object wrapped = JSONObject.wrap(value); - jsonValue = wrapped != null ? wrapped : value.toString(); - } else if (value == null) { - // This is used by UnitTest only - jsonValue = JSONObject.NULL; - } else if (value.getClass().isArray()) { - // This is used by UnitTest only - final JSONArray jsonArray = new JSONArray(); - for (int j = 0; j < Array.getLength(value); j++) { - jsonArray.put(Array.get(value, j)); - } - jsonValue = jsonArray; } else { - // This is used by UnitTest only - jsonValue = value; + final Object wrapped = JSONObject.wrap(value); + jsonValue = (wrapped != null) ? wrapped : String.valueOf(value); } + out.put(mMap.keyAt(i), jsonValue); } return out; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/HardwareCodecCapabilityUtils.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/HardwareCodecCapabilityUtils.java @@ -264,15 +264,13 @@ public final class HardwareCodecCapabilityUtils { for (final int colorFormat : capabilities.colorFormats) { Log.v(LOGTAG, " Color: 0x" + Integer.toHexString(colorFormat)); } - if (Build.VERSION.SDK_INT >= 24) { - for (final MediaCodecInfo.CodecProfileLevel pl : capabilities.profileLevels) { - Log.v( - LOGTAG, - " Profile: 0x" - + Integer.toHexString(pl.profile) - + "/Level=0x" - + Integer.toHexString(pl.level)); - } + for (final MediaCodecInfo.CodecProfileLevel pl : capabilities.profileLevels) { + Log.v( + LOGTAG, + " Profile: 0x" + + Integer.toHexString(pl.profile) + + "/Level=0x" + + Integer.toHexString(pl.level)); } final int codecColorFormat = getSupportsYUV420orNV12(capabilities); if (codecColorFormat != COLOR_FORMAT_NOT_SUPPORTED) { @@ -350,11 +348,6 @@ public final class HardwareCodecCapabilityUtils { @WrapForJNI public static boolean decodes10Bit(final String aMimeType) { - if (Build.VERSION.SDK_INT < 24) { - // Be conservative when we cannot get supported profile. - return false; - } - final MediaCodecList codecs = new MediaCodecList(MediaCodecList.REGULAR_CODECS); for (final MediaCodecInfo info : codecs.getCodecInfos()) { if (info.isEncoder()) { @@ -381,11 +374,6 @@ public final class HardwareCodecCapabilityUtils { } private static boolean is10BitVP9Profile(final int profile) { - if (Build.VERSION.SDK_INT < 24) { - // Be conservative when we cannot get supported profile. - return false; - } - if ((profile == MediaCodecInfo.CodecProfileLevel.VP9Profile2) || (profile == MediaCodecInfo.CodecProfileLevel.VP9Profile3) || (profile == MediaCodecInfo.CodecProfileLevel.VP9Profile2HDR) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/Autofill.java @@ -8,7 +8,6 @@ package org.mozilla.geckoview; import android.graphics.Rect; import android.graphics.RectF; -import android.os.Build; import android.util.Log; import android.util.SparseArray; import android.view.View; @@ -18,7 +17,6 @@ import androidx.annotation.AnyThread; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.UiThread; import androidx.collection.ArrayMap; import java.lang.annotation.Retention; @@ -466,7 +464,6 @@ public class Autofill { * @param structure The view structure to fill * @param flags The autofill flags */ - @RequiresApi(Build.VERSION_CODES.M) @UiThread public void fillViewStructure( @NonNull final View view, @NonNull final ViewStructure structure, final int flags) { @@ -482,7 +479,6 @@ public class Autofill { * @param structure The view structure to fill * @param flags The autofill flags */ - @RequiresApi(Build.VERSION_CODES.M) @UiThread public void fillViewStructure( final @NonNull Node node, @@ -500,26 +496,22 @@ public class Autofill { return; } - if (Build.VERSION.SDK_INT >= 26) { - structure.setAutofillId(view.getAutofillId(), data.id); - structure.setWebDomain(node.getDomain()); - structure.setAutofillValue(AutofillValue.forText(data.value)); - } + structure.setAutofillId(view.getAutofillId(), data.id); + structure.setWebDomain(node.getDomain()); + structure.setAutofillValue(AutofillValue.forText(data.value)); structure.setId(data.id, null, null, null); // This dimensions doesn't seem to used for autofill service. structure.setDimens(0, 0, 0, 0, node.getDimensions().width(), node.getDimensions().height()); - if (Build.VERSION.SDK_INT >= 26) { - final ViewStructure.HtmlInfo.Builder htmlBuilder = - structure.newHtmlInfoBuilder(node.getTag()); - for (final String key : node.getAttributes().keySet()) { - htmlBuilder.addAttribute(key, String.valueOf(node.getAttribute(key))); - } - - structure.setHtmlInfo(htmlBuilder.build()); + final ViewStructure.HtmlInfo.Builder htmlBuilder = + structure.newHtmlInfoBuilder(node.getTag()); + for (final String key : node.getAttributes().keySet()) { + htmlBuilder.addAttribute(key, String.valueOf(node.getAttribute(key))); } + structure.setHtmlInfo(htmlBuilder.build()); + structure.setChildCount(node.getChildren().size()); int childCount = 0; @@ -537,10 +529,7 @@ public class Autofill { structure.setFocusable(node.getFocusable()); structure.setFocused(node.equals(getFocused())); structure.setVisibility(isVisible(node) ? View.VISIBLE : View.INVISIBLE); - - if (Build.VERSION.SDK_INT >= 26) { - structure.setAutofillType(View.AUTOFILL_TYPE_TEXT); - } + structure.setAutofillType(View.AUTOFILL_TYPE_TEXT); break; default: if (childCount > 0) { @@ -551,7 +540,7 @@ public class Autofill { break; } - if (Build.VERSION.SDK_INT < 26 || !"input".equals(node.getTag())) { + if (!"input".equals(node.getTag())) { return; } // LastPass will fill password to the field where setAutofillHints diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java @@ -16,7 +16,6 @@ import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; import android.graphics.RectF; -import android.os.Build; import android.os.TransactionTooLargeException; import android.text.TextUtils; import android.util.Log; @@ -26,7 +25,6 @@ import android.view.MenuItem; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.UiThread; import java.util.ArrayList; import java.util.List; @@ -93,7 +91,6 @@ public class BasicSelectionActionDelegate private @Nullable ActionMode mActionModeForClipboardPermission; - @RequiresApi(Build.VERSION_CODES.M) private class Callback2Wrapper extends ActionMode.Callback2 { @Override public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) { @@ -128,7 +125,7 @@ public class BasicSelectionActionDelegate * @param activity The activity to associate with this delegate */ public BasicSelectionActionDelegate(final @NonNull Activity activity) { - this(activity, Build.VERSION.SDK_INT >= 23); + this(activity, true); } /** @@ -189,10 +186,6 @@ public class BasicSelectionActionDelegate return false; } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O && ACTION_PASTE_AS_PLAIN_TEXT.equals(id)) { - return false; - } - if (mExternalActionsEnabled && !mSelection.text.isEmpty() && ACTION_PROCESS_TEXT.equals(id)) { return !getProcessTextExportedActivities().isEmpty(); } @@ -254,9 +247,6 @@ public class BasicSelectionActionDelegate item.setTitle(android.R.string.paste); break; case ACTION_PASTE_AS_PLAIN_TEXT: - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - throw new IllegalStateException("Unexpected version for action"); - } item.setTitle(android.R.string.paste_as_plain_text); break; case ACTION_SELECT_ALL: @@ -360,7 +350,7 @@ public class BasicSelectionActionDelegate final String[] allActions = getAllActions(); for (final String actionId : allActions) { if (isActionAvailable(actionId)) { - if (!mUseFloatingToolbar && (Build.VERSION.SDK_INT == 22 || Build.VERSION.SDK_INT == 23)) { + if (!mUseFloatingToolbar) { // Android bug where onPrepareActionMode is not called initially. onPrepareActionMode(actionMode, menu); } @@ -498,7 +488,6 @@ public class BasicSelectionActionDelegate transformedRect.roundOut(outRect); } - @RequiresApi(Build.VERSION_CODES.M) @Override public void onShowActionRequest(final GeckoSession session, final Selection selection) { ThreadUtils.assertOnUiThread(); @@ -586,7 +575,6 @@ public class BasicSelectionActionDelegate } /** Callback class of clipboard permission for Android M+ */ - @RequiresApi(Build.VERSION_CODES.M) private class ClipboardPermissionCallbackM extends ActionMode.Callback2 { private @Nullable GeckoResult<AllowOrDeny> mResult; private final @NonNull GeckoSession mSession; @@ -648,7 +636,6 @@ public class BasicSelectionActionDelegate * @return A {@link GeckoResult} with {@link AllowOrDeny}, determining the response to the * permission request for this site. */ - @RequiresApi(Build.VERSION_CODES.M) @Override public GeckoResult<AllowOrDeny> onShowClipboardPermissionRequest( final GeckoSession session, final ClipboardPermission permission) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashHandler.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashHandler.java @@ -12,7 +12,6 @@ import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.Process; import android.util.Log; @@ -354,7 +353,6 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler { @NonNull final String dumpFile, @NonNull final String extraFile) { try { final Context context = getAppContext(); - final ProcessBuilder pb; if (mHandlerService == null) { Log.w(LOGTAG, "No crash handler service defined, unable to report crash"); @@ -371,67 +369,32 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler { intent.putExtra(GeckoRuntime.EXTRA_CRASH_PROCESS_TYPE, "main"); intent.setClass(context, mHandlerService); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(intent); - } else { - context.startService(intent); - } + context.startForegroundService(intent); return true; } - final int deviceSdkVersion = Build.VERSION.SDK_INT; - if (deviceSdkVersion < 17) { - pb = - new ProcessBuilder( - "/system/bin/am", - "startservice", - "-a", - GeckoRuntime.ACTION_CRASHED, - "-n", - getAppPackageName() + '/' + mHandlerService.getName(), - "--es", - GeckoRuntime.EXTRA_MINIDUMP_PATH, - dumpFile, - "--es", - GeckoRuntime.EXTRA_EXTRAS_PATH, - extraFile, - "--es", - GeckoRuntime.EXTRA_CRASH_PROCESS_VISIBILITY, - GeckoRuntime.CRASHED_PROCESS_VISIBILITY_MAIN, - "--es", - GeckoRuntime.EXTRA_CRASH_PROCESS_TYPE, - "main"); - } else { - final String startServiceCommand; - if (deviceSdkVersion >= 26) { - startServiceCommand = "start-foreground-service"; - } else { - startServiceCommand = "startservice"; - } - - pb = - new ProcessBuilder( - "/system/bin/am", - startServiceCommand, - "--user", /* USER_CURRENT_OR_SELF */ - "-3", - "-a", - GeckoRuntime.ACTION_CRASHED, - "-n", - getAppPackageName() + '/' + mHandlerService.getName(), - "--es", - GeckoRuntime.EXTRA_MINIDUMP_PATH, - dumpFile, - "--es", - GeckoRuntime.EXTRA_EXTRAS_PATH, - extraFile, - "--es", - GeckoRuntime.EXTRA_CRASH_PROCESS_VISIBILITY, - GeckoRuntime.CRASHED_PROCESS_VISIBILITY_MAIN, - "--es", - GeckoRuntime.EXTRA_CRASH_PROCESS_TYPE, - "main"); - } + final ProcessBuilder pb = + new ProcessBuilder( + "/system/bin/am", + "start-foreground-service", + "--user", + /* USER_CURRENT_OR_SELF */ "-3", + "-a", + GeckoRuntime.ACTION_CRASHED, + "-n", + getAppPackageName() + '/' + mHandlerService.getName(), + "--es", + GeckoRuntime.EXTRA_MINIDUMP_PATH, + dumpFile, + "--es", + GeckoRuntime.EXTRA_EXTRAS_PATH, + extraFile, + "--es", + GeckoRuntime.EXTRA_CRASH_PROCESS_VISIBILITY, + GeckoRuntime.CRASHED_PROCESS_VISIBILITY_MAIN, + "--es", + GeckoRuntime.EXTRA_CRASH_PROCESS_TYPE, + "main"); pb.start().waitFor(); diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoEditable.java @@ -1987,7 +1987,7 @@ import org.mozilla.geckoview.SessionTextInput.EditableListener.IMEState; outAttrs.imeOptions |= InputMethods.IME_FLAG_NO_PERSONALIZED_LEARNING; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && typeHint.length() == 0) { + if (typeHint.length() == 0) { // contenteditable allows image insertion. outAttrs.contentMimeTypes = new String[] {"image/gif", "image/jpeg", "image/png"}; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java @@ -10,7 +10,6 @@ import android.content.res.Configuration; import android.graphics.Matrix; import android.graphics.RectF; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -29,7 +28,6 @@ import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputContentInfo; import androidx.annotation.NonNull; -import androidx.annotation.RequiresApi; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -537,8 +535,8 @@ import org.mozilla.gecko.util.ThreadUtils; // changes, we gracefully fall back to using the regular Handler. if ("startInputInner".equals(frame.getMethodName()) && "android.view.inputmethod.InputMethodManager".equals(frame.getClassName())) { - // Only return our own Handler to InputMethodManager and only prior to 24. - return Build.VERSION.SDK_INT < 24; + // Do not return our own Handler to InputMethodManager. + return false; } if (CUSTOM_HANDLER_TEST_METHOD.equals(frame.getMethodName()) && CUSTOM_HANDLER_TEST_CLASS.equals(frame.getClassName())) { @@ -692,11 +690,6 @@ import org.mozilla.gecko.util.ThreadUtils; && mKeyInputConnection.commitText(text, newCursorPosition); } - // Bug 1818268 - Unexpected crash on Galaxy J7 - if (InputMethods.dontOverrideCommitText()) { - return super.commitText(text, newCursorPosition); - } - // Default implementation is // 1. Set selection // 2. Call Editable.replace @@ -814,7 +807,6 @@ import org.mozilla.gecko.util.ThreadUtils; am.dispatchMediaKeyEvent(event); } - @RequiresApi(Build.VERSION_CODES.N_MR1) @Override public boolean commitContent( final InputContentInfo inputContentInfo, final int flags, final Bundle opts) { diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java @@ -18,7 +18,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.res.Configuration; -import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -218,7 +217,6 @@ public final class GeckoRuntime implements Parcelable { // Stop monitoring network status while inactive. GeckoNetworkManager.getInstance().stop(); GeckoThread.onPause(); - Clipboard.onPause(); } } @@ -367,11 +365,7 @@ public final class GeckoRuntime implements Parcelable { i.putExtra(EXTRA_CRASH_PROCESS_TYPE, message.getString(EXTRA_CRASH_PROCESS_TYPE)); i.putExtra(EXTRA_CRASH_REMOTE_TYPE, message.getString(EXTRA_CRASH_REMOTE_TYPE)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - context.startForegroundService(i); - } else { - context.startService(i); - } + context.startForegroundService(i); } else if ("GeckoView:ServiceWorkerOpenWindow".equals(event)) { final String url = message.getString("url", "about:blank"); serviceWorkerOpenWindow(url) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java @@ -6,8 +6,6 @@ package org.mozilla.geckoview; -import static android.os.Build.VERSION; - import android.app.Service; import android.graphics.Rect; import android.os.Build; @@ -78,9 +76,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { * Path to configuration file from which GeckoView will read configuration options such as Gecko * process arguments, environment variables, and preferences. * - * <p>Note: this feature is only available for <code>{@link VERSION#SDK_INT} > 21</code>, on - * older devices this will be silently ignored. - * * @param configFilePath Configuration file path to read from, or <code>null</code> to use * default location <code>/data/local/tmp/$PACKAGE-geckoview-config.yaml</code>. * @return This Builder instance. @@ -928,8 +923,6 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { * Path to configuration file from which GeckoView will read configuration options such as Gecko * process arguments, environment variables, and preferences. * - * <p>Note: this feature is only available for <code>{@link VERSION#SDK_INT} > 21</code>. - * * @return Path to configuration file from which GeckoView will read configuration options, or * <code>null</code> for default location <code>/data/local/tmp/$PACKAGE-geckoview-config.yaml * </code>. @@ -1508,18 +1501,12 @@ public final class GeckoRuntimeSettings extends RuntimeSettings { } private static String[] getSystemLocalesForAcceptLanguage() { - if (VERSION.SDK_INT >= 24) { - final LocaleList localeList = LocaleList.getDefault(); - final String[] locales = new String[localeList.size()]; - for (int i = 0; i < localeList.size(); i++) { - // accept-language should be language or language-region format. - locales[i] = LocaleUtils.getLanguageTagForAcceptLanguage(localeList.get(i)); - } - return locales; + final LocaleList localeList = LocaleList.getDefault(); + final String[] locales = new String[localeList.size()]; + for (int i = 0; i < localeList.size(); i++) { + // accept-language should be language or language-region format. + locales[i] = LocaleUtils.getLanguageTagForAcceptLanguage(localeList.get(i)); } - final String[] locales = new String[1]; - final Locale locale = Locale.getDefault(); - locales[0] = LocaleUtils.getLanguageTagForAcceptLanguage(locale); return locales; } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -4075,7 +4075,6 @@ public class GeckoSession { * @param session The GeckoSession that initiated the callback. * @param icon The pointer icon sent from the content. */ - @RequiresApi(Build.VERSION_CODES.N) @UiThread default void onPointerIconChange( @NonNull final GeckoSession session, @NonNull final PointerIcon icon) { @@ -6073,8 +6072,7 @@ public class GeckoSession { if (Type.FOLDER == type && uris[0] != null) { GeckoBundle[] filesInWebKitDirectory = filesInWebKitDirectory = new GeckoBundle[0]; try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N - && DocumentsContract.isTreeUri(uris[0])) { + if (DocumentsContract.isTreeUri(uris[0])) { filesInWebKitDirectory = IntentUtils.traverseTreeUri(context, uris[0]).stream() .map(f -> f.toGeckoBundle()) @@ -6097,7 +6095,7 @@ public class GeckoSession { return uri.getPath(); } if ("content".equals(uri.getScheme())) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && DocumentsContract.isTreeUri(uri)) { + if (DocumentsContract.isTreeUri(uri)) { return IntentUtils.resolveTreeUri(context, uri); } if (DocumentsContract.isDocumentUri(context, uri)) { @@ -7894,10 +7892,6 @@ public class GeckoSession { final int defaultCursor, final @Nullable Bitmap customCursor, final float x, final float y) { ThreadUtils.assertOnUiThread(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return; - } - final PointerIcon icon; if (customCursor != null) { try { @@ -7920,9 +7914,6 @@ public class GeckoSession { /* package */ void startDragAndDrop(final Bitmap bitmap) { ThreadUtils.assertOnUiThread(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return; - } final View view = getTextInput().getView(); if (view == null) { return; @@ -7934,9 +7925,6 @@ public class GeckoSession { /* package */ void updateDragImage(final Bitmap bitmap) { ThreadUtils.assertOnUiThread(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return; - } final View view = getTextInput().getView(); if (view == null) { return; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java @@ -52,7 +52,6 @@ import androidx.annotation.AnyThread; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.UiThread; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; @@ -329,12 +328,7 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro mSelectionActionDelegate = new BasicSelectionActionDelegate(activity); } - if (Build.VERSION.SDK_INT >= 26) { - mAutofillDelegate = new AndroidAutofillDelegate(); - } else { - // We don't support Autofill on SDK < 26 - mAutofillDelegate = new Autofill.Delegate() {}; - } + mAutofillDelegate = new AndroidAutofillDelegate(); mPrintDelegate = new GeckoViewPrintDelegate(); } @@ -859,10 +853,7 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro @Override public Handler getHandler() { - if (Build.VERSION.SDK_INT >= 24 || mSession == null) { - return super.getHandler(); - } - return mSession.getTextInput().getHandler(super.getHandler()); + return super.getHandler(); } @Override @@ -992,7 +983,6 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro } @Override - @RequiresApi(Build.VERSION_CODES.O) public void onProvideAutofillVirtualStructure(final ViewStructure structure, final int flags) { if (mSession == null) { return; @@ -1006,7 +996,6 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro } @Override - @RequiresApi(Build.VERSION_CODES.O) public void autofill(@NonNull final SparseArray<AutofillValue> values) { // Note: we can't use mSession.getAutofillSession() because the app might have swapped // the session under us between the onProvideAutofillVirtualStructure and this call @@ -1055,7 +1044,6 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro * * @param enabled Whether or not Android autofill is enabled for this view. */ - @RequiresApi(Build.VERSION_CODES.O) public void setAutofillEnabled(final boolean enabled) { mAutofillEnabled = enabled; @@ -1071,12 +1059,10 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro /** * @return Whether or not Android autofill is enabled for this view. */ - @RequiresApi(Build.VERSION_CODES.O) public boolean getAutofillEnabled() { return mAutofillEnabled; } - @RequiresApi(Build.VERSION_CODES.O) private class AndroidAutofillDelegate implements Autofill.Delegate { AutofillManager mAutofillManager; boolean mDisabled = false; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java @@ -9,7 +9,6 @@ import android.app.UiModeManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; -import android.os.Build; import android.os.SystemClock; import android.util.Log; import android.util.Pair; @@ -646,10 +645,6 @@ public class PanZoomController { public boolean onDragEvent(@NonNull final DragEvent event) { ThreadUtils.assertOnUiThread(); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { - return false; - } - if (!mAttached) { // This might be during start up, so we cannot handle drag event. return false; diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java @@ -8,7 +8,6 @@ package org.mozilla.geckoview; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; -import android.os.Build; import android.os.Bundle; import android.text.InputType; import android.text.TextUtils; @@ -819,9 +818,7 @@ public class SessionAccessibility { final Bundle bundle = node.getExtras(); if (hint != null) { bundle.putCharSequence("AccessibilityNodeInfo.hint", hint); - if (Build.VERSION.SDK_INT >= 26) { - node.setHintText(hint); - } + node.setHintText(hint); } if (geckoRole != null) { bundle.putCharSequence("AccessibilityNodeInfo.geckoRole", geckoRole); @@ -850,10 +847,7 @@ public class SessionAccessibility { } } - // SDK 23 and above - if (Build.VERSION.SDK_INT >= 23) { - node.setContextClickable((flags & FLAG_CONTEXT_CLICKABLE) != 0); - } + node.setContextClickable((flags & FLAG_CONTEXT_CLICKABLE) != 0); } @WrapForJNI diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java @@ -286,21 +286,7 @@ public final class SessionTextInput { } /** - * Get a Handler for the background input method thread. In order to use a background thread for - * input method operations on systems prior to Nougat, first override {@code View.getHandler()} - * for the View returning the InputConnection instance, and then call this method from the - * overridden method. - * - * <p>For example: - * - * <pre> - * @Override - * public Handler getHandler() { - * if (Build.VERSION.SDK_INT >= 24) { - * return super.getHandler(); - * } - * return getSession().getTextInput().getHandler(super.getHandler()); - * }</pre> + * Get a Handler for the background input method thread. * * @param defHandler Handler returned by the system {@code getHandler} implementation. * @return Handler to return to the system through {@code getHandler}. diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md @@ -1855,4 +1855,4 @@ to allow adding gecko profiler markers. [65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String) [65.25]: {{javadoc_uri}}/GeckoResult.html -[api-version]: bfecdf1c171f62dba8161757bdb91d3345b9283c +[api-version]: 0b8df0addbfebea852867d9ded1548f2b365839d diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java @@ -18,7 +18,6 @@ import android.database.Cursor; import android.graphics.Color; import android.graphics.PorterDuff; import android.net.Uri; -import android.os.Build; import android.provider.OpenableColumns; import android.text.InputType; import android.text.format.DateFormat; @@ -736,26 +735,14 @@ final class BasicGeckoViewPrompt implements GeckoSession.PromptDelegate { return defaultToNow ? new Date() : null; } - @SuppressWarnings("deprecation") private static void setTimePickerTime(final TimePicker picker, final Calendar cal) { - if (Build.VERSION.SDK_INT >= 23) { - picker.setHour(cal.get(Calendar.HOUR_OF_DAY)); - picker.setMinute(cal.get(Calendar.MINUTE)); - } else { - picker.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY)); - picker.setCurrentMinute(cal.get(Calendar.MINUTE)); - } + picker.setHour(cal.get(Calendar.HOUR_OF_DAY)); + picker.setMinute(cal.get(Calendar.MINUTE)); } - @SuppressWarnings("deprecation") private static void setCalendarTime(final Calendar cal, final TimePicker picker) { - if (Build.VERSION.SDK_INT >= 23) { - cal.set(Calendar.HOUR_OF_DAY, picker.getHour()); - cal.set(Calendar.MINUTE, picker.getMinute()); - } else { - cal.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour()); - cal.set(Calendar.MINUTE, picker.getCurrentMinute()); - } + cal.set(Calendar.HOUR_OF_DAY, picker.getHour()); + cal.set(Calendar.MINUTE, picker.getMinute()); } @Override diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/ExampleCrashHandler.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/ExampleCrashHandler.java @@ -10,7 +10,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; -import android.os.Build; import android.os.IBinder; import android.os.StrictMode; import android.util.Log; @@ -54,9 +53,7 @@ public class ExampleCrashHandler extends Service { String id = createNotificationChannel(); int intentFlag = 0; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - intentFlag = PendingIntent.FLAG_IMMUTABLE; - } + intentFlag = PendingIntent.FLAG_IMMUTABLE; PendingIntent reportIntent = PendingIntent.getService( @@ -124,15 +121,11 @@ public class ExampleCrashHandler extends Service { } private String createNotificationChannel() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel channel = - new NotificationChannel( - CHANNEL_ID, "GeckoView Example Crashes", NotificationManager.IMPORTANCE_LOW); - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - return CHANNEL_ID; - } - - return ""; + NotificationChannel channel = + new NotificationChannel( + CHANNEL_ID, "GeckoView Example Crashes", NotificationManager.IMPORTANCE_LOW); + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + return CHANNEL_ID; } } diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java @@ -501,19 +501,14 @@ public class GeckoViewActivity extends AppCompatActivity private HashMap<Integer, GeckoResult<Intent>> mPendingActivityResult = new HashMap<>(); private boolean supportsPip() { - return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - && getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); + return getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); } private boolean maybeEnterPip() { if (!supportsPip()) return false; if (!mPipFullscreenMedia || !mPipIsPlaying) return false; try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - enterPictureInPictureMode(new PictureInPictureParams.Builder().build()); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - enterPictureInPictureMode(); - } + enterPictureInPictureMode(new PictureInPictureParams.Builder().build()); return true; } catch (IllegalStateException e) { return false; @@ -974,60 +969,57 @@ public class GeckoViewActivity extends AppCompatActivity } }); - // `getSystemService` call requires API level 23 - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { - sGeckoRuntime.setWebNotificationDelegate( - new WebNotificationDelegate() { - NotificationManager notificationManager = getSystemService(NotificationManager.class); + sGeckoRuntime.setWebNotificationDelegate( + new WebNotificationDelegate() { + NotificationManager notificationManager = getSystemService(NotificationManager.class); - @Override - public void onShowNotification(@NonNull WebNotification notification) { - Intent clickIntent = new Intent(GeckoViewActivity.this, GeckoViewActivity.class); - clickIntent.putExtra("onClick", notification); - PendingIntent dismissIntent = - PendingIntent.getActivity( - GeckoViewActivity.this, mLastID, clickIntent, PendingIntent.FLAG_IMMUTABLE); - - NotificationCompat.Builder builder = - new NotificationCompat.Builder(GeckoViewActivity.this, CHANNEL_ID) - .setContentTitle(notification.title) - .setContentText(notification.text) - .setSmallIcon(R.drawable.ic_status_logo) - .setContentIntent(dismissIntent) - .setAutoCancel(true); - - mNotificationIDMap.put(notification.tag, mLastID); - - if (notification.imageUrl != null && notification.imageUrl.length() > 0) { - final GeckoWebExecutor executor = new GeckoWebExecutor(sGeckoRuntime); - - GeckoResult<WebResponse> response = - executor.fetch( - new WebRequest.Builder(notification.imageUrl) - .addHeader("Accept", "image") - .build()); - response.accept( - value -> { - Bitmap bitmap = BitmapFactory.decodeStream(value.body); - builder.setLargeIcon(bitmap); - notificationManager.notify(mLastID++, builder.build()); - }); - } else { - notificationManager.notify(mLastID++, builder.build()); - } - notification.show(); + @Override + public void onShowNotification(@NonNull WebNotification notification) { + Intent clickIntent = new Intent(GeckoViewActivity.this, GeckoViewActivity.class); + clickIntent.putExtra("onClick", notification); + PendingIntent dismissIntent = + PendingIntent.getActivity( + GeckoViewActivity.this, mLastID, clickIntent, PendingIntent.FLAG_IMMUTABLE); + + NotificationCompat.Builder builder = + new NotificationCompat.Builder(GeckoViewActivity.this, CHANNEL_ID) + .setContentTitle(notification.title) + .setContentText(notification.text) + .setSmallIcon(R.drawable.ic_status_logo) + .setContentIntent(dismissIntent) + .setAutoCancel(true); + + mNotificationIDMap.put(notification.tag, mLastID); + + if (notification.imageUrl != null && notification.imageUrl.length() > 0) { + final GeckoWebExecutor executor = new GeckoWebExecutor(sGeckoRuntime); + + GeckoResult<WebResponse> response = + executor.fetch( + new WebRequest.Builder(notification.imageUrl) + .addHeader("Accept", "image") + .build()); + response.accept( + value -> { + Bitmap bitmap = BitmapFactory.decodeStream(value.body); + builder.setLargeIcon(bitmap); + notificationManager.notify(mLastID++, builder.build()); + }); + } else { + notificationManager.notify(mLastID++, builder.build()); } + notification.show(); + } - @Override - public void onCloseNotification(@NonNull WebNotification notification) { - if (mNotificationIDMap.containsKey(notification.tag)) { - int id = mNotificationIDMap.get(notification.tag); - notificationManager.cancel(id); - mNotificationIDMap.remove(notification.tag); - } + @Override + public void onCloseNotification(@NonNull WebNotification notification) { + if (mNotificationIDMap.containsKey(notification.tag)) { + int id = mNotificationIDMap.get(notification.tag); + notificationManager.cancel(id); + mNotificationIDMap.remove(notification.tag); } - }); - } + } + }); sGeckoRuntime.setDelegate( () -> { @@ -1178,19 +1170,15 @@ public class GeckoViewActivity extends AppCompatActivity } private void createNotificationChannel() { - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - CharSequence name = getString(R.string.app_name); - String description = getString(R.string.activity_label); - int importance = NotificationManager.IMPORTANCE_DEFAULT; - NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); - channel.setDescription(description); - // Register the channel with the system; you can't change the importance - // or other notification behaviors after this - NotificationManager notificationManager = getSystemService(NotificationManager.class); - notificationManager.createNotificationChannel(channel); - } + CharSequence name = getString(R.string.app_name); + String description = getString(R.string.activity_label); + int importance = NotificationManager.IMPORTANCE_DEFAULT; + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); } private TabSession createSession(final @Nullable String cookieStoreId) { @@ -1519,9 +1507,7 @@ public class GeckoViewActivity extends AppCompatActivity supportedLanguages -> { // Just a check if sorting is working on the Language object by reversing, Languages // should generally come from the API in the display order. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - Collections.reverse(supportedLanguages.fromLanguages); - } + Collections.reverse(supportedLanguages.fromLanguages); ArrayAdapter<TranslationsController.Language> fromData = new ArrayAdapter<TranslationsController.Language>( this.getBaseContext(), @@ -2383,13 +2369,8 @@ public class GeckoViewActivity extends AppCompatActivity @Override public void onAndroidPermissionsRequest( final GeckoSession session, final String[] permissions, final Callback callback) { - if (Build.VERSION.SDK_INT >= 23) { - // requestPermissions was introduced in API 23. - mCallback = callback; - requestPermissions(permissions, androidPermissionRequestCode); - } else { - callback.grant(); - } + mCallback = callback; + requestPermissions(permissions, androidPermissionRequestCode); } @Override diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -249,10 +249,6 @@ static XP_CHAR lastCrashTimeFilename[XP_PATH_MAX] = {0}; // with the current process that gets lost when we fork so we need to // explicitly pass it to am static char* androidUserSerial = nullptr; - -// Before Android 8 we needed to use "startservice" to start the crash reporting -// service. After Android 8 we need to use "start-foreground-service" -static const char* androidStartServiceCommand = nullptr; #endif // this holds additional data sent via the API @@ -1279,14 +1275,14 @@ static bool LaunchCrashHandlerService(const XP_CHAR* aProgramPath, // Invoke the crash handler service using am if (androidUserSerial) { (void)execlp( - "/system/bin/am", "/system/bin/am", androidStartServiceCommand, + "/system/bin/am", "/system/bin/am", "start-foreground-service", "--user", androidUserSerial, "-a", "org.mozilla.gecko.ACTION_CRASHED", "-n", aProgramPath, "--es", "minidumpPath", aMinidumpPath, "--es", "extrasPath", extrasPath, "--ez", "fatal", "true", "--es", "processVisibility", "MAIN", "--es", "processType", "main", (char*)0); } else { (void)execlp( - "/system/bin/am", "/system/bin/am", androidStartServiceCommand, "-a", + "/system/bin/am", "/system/bin/am", "start-foreground-service", "-a", "org.mozilla.gecko.ACTION_CRASHED", "-n", aProgramPath, "--es", "minidumpPath", aMinidumpPath, "--es", "extrasPath", extrasPath, "--ez", "fatal", "true", "--es", "processVisibility", "MAIN", "--es", @@ -1947,17 +1943,6 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) { NS_WARNING("No Android crash handler set"); } - const char* deviceAndroidVersion = - PR_GetEnv("MOZ_ANDROID_DEVICE_SDK_VERSION"); - if (deviceAndroidVersion != nullptr) { - const int deviceSdkVersion = atol(deviceAndroidVersion); - if (deviceSdkVersion >= 26) { - androidStartServiceCommand = (char*)"start-foreground-service"; - } else { - androidStartServiceCommand = (char*)"startservice"; - } - } - const char* crashHelperPathEnv = PR_GetEnv("MOZ_ANDROID_PACKAGE_NAME"); MOZ_ASSERT(crashHelperPathEnv, "The application package name is required"); crashHelperPath = crashHelperPathEnv;